From: <cap...@us...> - 2007-03-16 15:33:15
|
Revision: 2 http://svn.sourceforge.net/pearcolator/?rev=2&view=rev Author: captain5050 Date: 2007-03-16 08:33:01 -0700 (Fri, 16 Mar 2007) Log Message: ----------- Restructure files and imports following Jikes RVM restructuring Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java src/org/binarytranslator/vmInterface/DBT_OptimizingCompilerException.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java src/org/binarytranslator/vmInterface/TranslationHelper.java Added Paths: ----------- LICENSE.txt ext/org/ ext/org/jikesrvm/ ext/org/jikesrvm/opt/ ext/org/jikesrvm/opt/ir/ ext/org/jikesrvm/opt/ir/OPT_HIRGenerator.java Removed Paths: ------------- LICENSE ext/com/ Deleted: LICENSE =================================================================== --- LICENSE 2006-12-07 14:54:50 UTC (rev 1) +++ LICENSE 2007-03-16 15:33:01 UTC (rev 2) @@ -1,247 +0,0 @@ - Common Public License - v 1.0 - - THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON - PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF - THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - - 1. DEFINITIONS - - "Contribution" means: - - a) in the case of the initial Contributor, the initial code and - documentation distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - - i) changes to the Program, and - - ii) additions to the Program; - - where such changes and/or additions to the Program originate from - and are distributed by that particular Contributor. A Contribution - 'originates' from a Contributor if it was added to the Program by - such Contributor itself or anyone acting on such Contributor's - behalf. Contributions do not include additions to the Program - which: (i) are separate modules of software distributed in - conjunction with the Program under their own license agreement, and - (ii) are not derivative works of the Program. - - "Contributor" means any person or entity that distributes the - Program. - - "Licensed Patents" mean patent claims licensable by a Contributor - which are necessarily infringed by the use or sale of its - Contribution alone or when combined with the Program. - - "Program" means the Contributions distributed in accordance with - this Agreement. - - "Recipient" means anyone who receives the Program under this - Agreement, including all Contributors. - - - 2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free - copyright license to reproduce, prepare derivative works of, - publicly display, publicly perform, distribute and sublicense - the Contribution of such Contributor, if any, and such - derivative works, in source code and object code form. - - b) Subject to the terms of this Agreement, each Contributor hereby - grants Recipient a non-exclusive, worldwide, royalty-free - patent license under Licensed Patents to make, use, sell, offer - to sell, import and otherwise transfer the Contribution of such - Contributor, if any, in source code and object code form. This - patent license shall apply to the combination of the - Contribution and the Program if, at the time the Contribution - is added by the Contributor, such addition of the Contribution - causes such combination to be covered by the Licensed - Patents. The patent license shall not apply to any other - combinations which include the Contribution. No hardware per se - is licensed hereunder. - - c) Recipient understands that although each Contributor grants the - licenses to its Contributions set forth herein, no assurances - are provided by any Contributor that the Program does not - infringe the patent or other intellectual property rights of - any other entity. Each Contributor disclaims any liability to - Recipient for claims brought by any other entity based on - infringement of intellectual property rights or otherwise. As - a condition to exercising the rights and licenses granted - hereunder, each Recipient hereby assumes sole responsibility to - secure any other intellectual property rights needed, if any. - For example, if a third party patent license is required to - allow Recipient to distribute the Program, it is Recipient's - responsibility to acquire that license before distributing the - Program. - - d) Each Contributor represents that to its knowledge it has - sufficient copyright rights in its Contribution, if any, to - grant the copyright license set forth in this Agreement. - - 3. REQUIREMENTS - - A Contributor may choose to distribute the Program in object code - form under its own license agreement, provided that: - - a) it complies with the terms and conditions of this Agreement; and - - b) its license agreement: - - i) effectively disclaims on behalf of all Contributors all - warranties and conditions, express and implied, including - warranties or conditions of title and non-infringement, and - implied warranties or conditions of merchantability and fitness - for a particular purpose; - - ii) effectively excludes on behalf of all Contributors all - liability for damages, including direct, indirect, special, - incidental and consequential damages, such as lost profits; - - iii) states that any provisions which differ from this Agreement - are offered by that Contributor alone and not by any other - party; and - - iv) states that source code for the Program is available from such - Contributor, and informs licensees how to obtain it in a - reasonable manner on or through a medium customarily used for - software exchange. - - When the Program is made available in source code form: - - a) it must be made available under this Agreement; and - - b) a copy of this Agreement must be included with each copy of the - Program. - - Contributors may not remove or alter any copyright notices - contained within the Program. - - Each Contributor must identify itself as the originator of its - Contribution, if any, in a manner that reasonably allows subsequent - Recipients to identify the originator of the Contribution. - - 4. COMMERCIAL DISTRIBUTION - - Commercial distributors of software may accept certain - responsibilities with respect to end users, business partners and - the like. While this license is intended to facilitate the - commercial use of the Program, the Contributor who includes the - Program in a commercial product offering should do so in a manner - which does not create potential liability for other - Contributors. Therefore, if a Contributor includes the Program in a - commercial product offering, such Contributor ("Commercial - Contributor") hereby agrees to defend and indemnify every other - Contributor ("Indemnified Contributor") against any losses, damages - and costs (collectively "Losses") arising from claims, lawsuits and - other legal actions brought by a third party against the - Indemnified Contributor to the extent caused by the acts or - omissions of such Commercial Contributor in connection with its - distribution of the Program in a commercial product offering. The - obligations in this section do not apply to any claims or Losses - relating to any actual or alleged intellectual property - infringement. In order to qualify, an Indemnified Contributor - must: a) promptly notify the Commercial Contributor in writing of - such claim, and b) allow the Commercial Contributor to control, and - cooperate with the Commercial Contributor in, the defense and any - related settlement negotiations. The Indemnified Contributor may - participate in any such claim at its own expense. - - For example, a Contributor might include the Program in a - commercial product offering, Product X. That Contributor is then a - Commercial Contributor. If that Commercial Contributor then makes - performance claims, or offers warranties related to Product X, - those performance claims and warranties are such Commercial - Contributor's responsibility alone. Under this section, the - Commercial Contributor would have to defend claims against the - other Contributors related to those performance claims and - warranties, and if a court requires any other Contributor to pay - any damages as a result, the Commercial Contributor must pay those - damages. - - 5. NO WARRANTY - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS - PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF - ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, - ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each - Recipient is solely responsible for determining the appropriateness - of using and distributing the Program and assumes all risks - associated with its exercise of rights under this Agreement, - including but not limited to the risks and costs of program errors, - compliance with applicable laws, damage to or loss of data, - programs or equipment, and unavailability or interruption of - operations. - - 6. DISCLAIMER OF LIABILITY - - EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT - NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY - RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGES. - - 7. GENERAL - - If any provision of this Agreement is invalid or unenforceable - under applicable law, it shall not affect the validity or - enforceability of the remainder of the terms of this Agreement, and - without further action by the parties hereto, such provision shall - be reformed to the minimum extent necessary to make such provision - valid and enforceable. - - If Recipient institutes patent litigation against a Contributor - with respect to a patent applicable to software (including a - cross-claim or counterclaim in a lawsuit), then any patent licenses - granted by that Contributor to such Recipient under this Agreement - shall terminate as of the date such litigation is filed. In - addition, if Recipient institutes patent litigation against any - entity (including a cross-claim or counterclaim in a lawsuit) - alleging that the Program itself (excluding combinations of the - Program with other software or hardware) infringes such Recipient's - patent(s), then such Recipient's rights granted under Section 2(b) - shall terminate as of the date such litigation is filed. - - All Recipient's rights under this Agreement shall terminate if it - fails to comply with any of the material terms or conditions of - this Agreement and does not cure such failure in a reasonable - period of time after becoming aware of such noncompliance. If all - Recipient's rights under this Agreement terminate, Recipient agrees - to cease use and distribution of the Program as soon as reasonably - practicable. However, Recipient's obligations under this Agreement - and any licenses granted by Recipient relating to the Program shall - continue and survive. - - Everyone is permitted to copy and distribute copies of this - Agreement, but in order to avoid inconsistency the Agreement is - copyrighted and may only be modified in the following manner. The - Agreement Steward reserves the right to publish new versions - (including revisions) of this Agreement from time to time. No one - other than the Agreement Steward has the right to modify this - Agreement. IBM is the initial Agreement Steward. IBM may assign - the responsibility to serve as the Agreement Steward to a suitable - separate entity. Each new version of the Agreement will be given a - distinguishing version number. The Program (including - Contributions) may always be distributed subject to the version of - the Agreement under which it was received. In addition, after a new - version of the Agreement is published, Contributor may elect to - distribute the Program (including its Contributions) under the new - version. Except as expressly stated in Sections 2(a) and 2(b) - above, Recipient receives no rights or licenses to the intellectual - property of any Contributor under this Agreement, whether - expressly, by implication, estoppel or otherwise. All rights in the - Program not expressly granted under this Agreement are reserved. - - This Agreement is governed by the laws of the State of New York and - the intellectual property laws of the United States of America. No - party to this Agreement will bring a legal action under this - Agreement more than one year after the cause of action arose. Each - party waives its rights to a jury trial in any resulting - litigation. Copied: LICENSE.txt (from rev 1, LICENSE) =================================================================== --- LICENSE.txt (rev 0) +++ LICENSE.txt 2007-03-16 15:33:01 UTC (rev 2) @@ -0,0 +1,247 @@ + Common Public License - v 1.0 + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF + THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate from + and are distributed by that particular Contributor. A Contribution + 'originates' from a Contributor if it was added to the Program by + such Contributor itself or anyone acting on such Contributor's + behalf. Contributions do not include additions to the Program + which: (i) are separate modules of software distributed in + conjunction with the Program under their own license agreement, and + (ii) are not derivative works of the Program. + + "Contributor" means any person or entity that distributes the + Program. + + "Licensed Patents" mean patent claims licensable by a Contributor + which are necessarily infringed by the use or sale of its + Contribution alone or when combined with the Program. + + "Program" means the Contributions distributed in accordance with + this Agreement. + + "Recipient" means anyone who receives the Program under this + Agreement, including all Contributors. + + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free + copyright license to reproduce, prepare derivative works of, + publicly display, publicly perform, distribute and sublicense + the Contribution of such Contributor, if any, and such + derivative works, in source code and object code form. + + b) Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free + patent license under Licensed Patents to make, use, sell, offer + to sell, import and otherwise transfer the Contribution of such + Contributor, if any, in source code and object code form. This + patent license shall apply to the combination of the + Contribution and the Program if, at the time the Contribution + is added by the Contributor, such addition of the Contribution + causes such combination to be covered by the Licensed + Patents. The patent license shall not apply to any other + combinations which include the Contribution. No hardware per se + is licensed hereunder. + + c) Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances + are provided by any Contributor that the Program does not + infringe the patent or other intellectual property rights of + any other entity. Each Contributor disclaims any liability to + Recipient for claims brought by any other entity based on + infringement of intellectual property rights or otherwise. As + a condition to exercising the rights and licenses granted + hereunder, each Recipient hereby assumes sole responsibility to + secure any other intellectual property rights needed, if any. + For example, if a third party patent license is required to + allow Recipient to distribute the Program, it is Recipient's + responsibility to acquire that license before distributing the + Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to + grant the copyright license set forth in this Agreement. + + 3. REQUIREMENTS + + A Contributor may choose to distribute the Program in object code + form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and fitness + for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement + are offered by that Contributor alone and not by any other + party; and + + iv) states that source code for the Program is available from such + Contributor, and informs licensees how to obtain it in a + reasonable manner on or through a medium customarily used for + software exchange. + + When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the + Program. + + Contributors may not remove or alter any copyright notices + contained within the Program. + + Each Contributor must identify itself as the originator of its + Contribution, if any, in a manner that reasonably allows subsequent + Recipients to identify the originator of the Contribution. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain + responsibilities with respect to end users, business partners and + the like. While this license is intended to facilitate the + commercial use of the Program, the Contributor who includes the + Program in a commercial product offering should do so in a manner + which does not create potential liability for other + Contributors. Therefore, if a Contributor includes the Program in a + commercial product offering, such Contributor ("Commercial + Contributor") hereby agrees to defend and indemnify every other + Contributor ("Indemnified Contributor") against any losses, damages + and costs (collectively "Losses") arising from claims, lawsuits and + other legal actions brought by a third party against the + Indemnified Contributor to the extent caused by the acts or + omissions of such Commercial Contributor in connection with its + distribution of the Program in a commercial product offering. The + obligations in this section do not apply to any claims or Losses + relating to any actual or alleged intellectual property + infringement. In order to qualify, an Indemnified Contributor + must: a) promptly notify the Commercial Contributor in writing of + such claim, and b) allow the Commercial Contributor to control, and + cooperate with the Commercial Contributor in, the defense and any + related settlement negotiations. The Indemnified Contributor may + participate in any such claim at its own expense. + + For example, a Contributor might include the Program in a + commercial product offering, Product X. That Contributor is then a + Commercial Contributor. If that Commercial Contributor then makes + performance claims, or offers warranties related to Product X, + those performance claims and warranties are such Commercial + Contributor's responsibility alone. Under this section, the + Commercial Contributor would have to defend claims against the + other Contributors related to those performance claims and + warranties, and if a court requires any other Contributor to pay + any damages as a result, the Commercial Contributor must pay those + damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS + PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, + ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each + Recipient is solely responsible for determining the appropriateness + of using and distributing the Program and assumes all risks + associated with its exercise of rights under this Agreement, + including but not limited to the risks and costs of program errors, + compliance with applicable laws, damage to or loss of data, + programs or equipment, and unavailability or interruption of + operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT + NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY + RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable + under applicable law, it shall not affect the validity or + enforceability of the remainder of the terms of this Agreement, and + without further action by the parties hereto, such provision shall + be reformed to the minimum extent necessary to make such provision + valid and enforceable. + + If Recipient institutes patent litigation against a Contributor + with respect to a patent applicable to software (including a + cross-claim or counterclaim in a lawsuit), then any patent licenses + granted by that Contributor to such Recipient under this Agreement + shall terminate as of the date such litigation is filed. In + addition, if Recipient institutes patent litigation against any + entity (including a cross-claim or counterclaim in a lawsuit) + alleging that the Program itself (excluding combinations of the + Program with other software or hardware) infringes such Recipient's + patent(s), then such Recipient's rights granted under Section 2(b) + shall terminate as of the date such litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it + fails to comply with any of the material terms or conditions of + this Agreement and does not cure such failure in a reasonable + period of time after becoming aware of such noncompliance. If all + Recipient's rights under this Agreement terminate, Recipient agrees + to cease use and distribution of the Program as soon as reasonably + practicable. However, Recipient's obligations under this Agreement + and any licenses granted by Recipient relating to the Program shall + continue and survive. + + Everyone is permitted to copy and distribute copies of this + Agreement, but in order to avoid inconsistency the Agreement is + copyrighted and may only be modified in the following manner. The + Agreement Steward reserves the right to publish new versions + (including revisions) of this Agreement from time to time. No one + other than the Agreement Steward has the right to modify this + Agreement. IBM is the initial Agreement Steward. IBM may assign + the responsibility to serve as the Agreement Steward to a suitable + separate entity. Each new version of the Agreement will be given a + distinguishing version number. The Program (including + Contributions) may always be distributed subject to the version of + the Agreement under which it was received. In addition, after a new + version of the Agreement is published, Contributor may elect to + distribute the Program (including its Contributions) under the new + version. Except as expressly stated in Sections 2(a) and 2(b) + above, Recipient receives no rights or licenses to the intellectual + property of any Contributor under this Agreement, whether + expressly, by implication, estoppel or otherwise. All rights in the + Program not expressly granted under this Agreement are reserved. + + This Agreement is governed by the laws of the State of New York and + the intellectual property laws of the United States of America. No + party to this Agreement will bring a legal action under this + Agreement more than one year after the cause of action arose. Each + party waives its rights to a jury trial in any resulting + litigation. Copied: ext/org/jikesrvm/opt/ir/OPT_HIRGenerator.java (from rev 1, ext/com/ibm/jikesrvm/opt/ir/OPT_HIRGenerator.java) =================================================================== --- ext/org/jikesrvm/opt/ir/OPT_HIRGenerator.java (rev 0) +++ ext/org/jikesrvm/opt/ir/OPT_HIRGenerator.java 2007-03-16 15:33:01 UTC (rev 2) @@ -0,0 +1,15 @@ +/* + * (C) The University of Manchester 2003 - 2006 + */ +package org.jikesrvm.opt.ir; + +/** + * Interface implemented by all optimizing compiler HIR generators + * such as OPT_BC2HIR and DBT_HIRGenerator + */ +public interface OPT_HIRGenerator { + /** + * Method to create the HIR + */ + public void generateHIR(); +} Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-16 15:33:01 UTC (rev 2) @@ -16,53 +16,53 @@ import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; // General VM class -import com.ibm.jikesrvm.VM; +import org.jikesrvm.VM; // Classes to get at class types -import com.ibm.jikesrvm.classloader.VM_Class; -import com.ibm.jikesrvm.classloader.VM_Method; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.classloader.VM_MethodReference; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_FieldReference; -import com.ibm.jikesrvm.classloader.VM_BootstrapClassLoader; -import com.ibm.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_Class; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_FieldReference; +import org.jikesrvm.classloader.VM_BootstrapClassLoader; +import org.jikesrvm.classloader.VM_Atom; // OPT interface -import com.ibm.jikesrvm.opt.OPT_Constants; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; -import com.ibm.jikesrvm.opt.ir.OPT_IR; +import org.jikesrvm.opt.OPT_Constants; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_IR; // Instructions -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_Operator; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.Athrow; -import com.ibm.jikesrvm.opt.ir.Binary; -import com.ibm.jikesrvm.opt.ir.BBend; -import com.ibm.jikesrvm.opt.ir.BooleanCmp; -import com.ibm.jikesrvm.opt.ir.Call; -import com.ibm.jikesrvm.opt.ir.CondMove; -import com.ibm.jikesrvm.opt.ir.GetField; -import com.ibm.jikesrvm.opt.ir.Goto; -import com.ibm.jikesrvm.opt.ir.IfCmp; -import com.ibm.jikesrvm.opt.ir.Move; -import com.ibm.jikesrvm.opt.ir.New; -import com.ibm.jikesrvm.opt.ir.LookupSwitch; -import com.ibm.jikesrvm.opt.ir.PutField; -import com.ibm.jikesrvm.opt.ir.Unary; +import org.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_Operator; +import org.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.Athrow; +import org.jikesrvm.opt.ir.Binary; +import org.jikesrvm.opt.ir.BBend; +import org.jikesrvm.opt.ir.BooleanCmp; +import org.jikesrvm.opt.ir.Call; +import org.jikesrvm.opt.ir.CondMove; +import org.jikesrvm.opt.ir.GetField; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.Move; +import org.jikesrvm.opt.ir.New; +import org.jikesrvm.opt.ir.LookupSwitch; +import org.jikesrvm.opt.ir.PutField; +import org.jikesrvm.opt.ir.Unary; // Operands -import com.ibm.jikesrvm.opt.ir.OPT_AddressConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; -import com.ibm.jikesrvm.opt.ir.OPT_BranchOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchProfileOperand; -import com.ibm.jikesrvm.opt.ir.OPT_ConditionOperand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_LocationOperand; -import com.ibm.jikesrvm.opt.ir.OPT_MethodOperand; -import com.ibm.jikesrvm.opt.ir.OPT_Operand; -import com.ibm.jikesrvm.opt.ir.OPT_Register; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TrueGuardOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TypeOperand; +import org.jikesrvm.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.ir.OPT_BranchOperand; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_LocationOperand; +import org.jikesrvm.opt.ir.OPT_MethodOperand; +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_Register; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.opt.ir.OPT_TypeOperand; // Java utilities import java.util.Enumeration; import java.util.NoSuchElementException; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-16 15:33:01 UTC (rev 2) @@ -14,10 +14,10 @@ import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.decoder.InstructionDecoder; -import com.ibm.jikesrvm.opt.ir.*; -import com.ibm.jikesrvm.*; -import com.ibm.jikesrvm.classloader.*; -import com.ibm.jikesrvm.opt.*; +import org.jikesrvm.opt.ir.*; +import org.jikesrvm.*; +import org.jikesrvm.classloader.*; +import org.jikesrvm.opt.*; import java.util.Enumeration; import java.util.NoSuchElementException; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_Laziness.java 2007-03-16 15:33:01 UTC (rev 2) @@ -10,8 +10,6 @@ import org.binarytranslator.generic.decoder.Laziness; -import com.ibm.jikesrvm.VM; - /** * A representation of the lazy state. This and a PC address define * what a block of code is good for. We don't use lazy evaluation for Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,8 +8,8 @@ */ package org.binarytranslator.arch.ppc.os.process; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; import org.binarytranslator.arch.ppc.decoder.PPC2IR; Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-03-16 15:33:01 UTC (rev 2) @@ -21,59 +21,59 @@ import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_Atom; // General VM class -import com.ibm.jikesrvm.VM; +import org.jikesrvm.VM; // Classes to get at class types -import com.ibm.jikesrvm.classloader.VM_Class; -import com.ibm.jikesrvm.classloader.VM_Method; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.classloader.VM_MethodReference; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_FieldReference; -import com.ibm.jikesrvm.classloader.VM_BootstrapClassLoader; -import com.ibm.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_Class; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_FieldReference; +import org.jikesrvm.classloader.VM_BootstrapClassLoader; +import org.jikesrvm.classloader.VM_Atom; // OPT interface -import com.ibm.jikesrvm.opt.OPT_Constants; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; -import com.ibm.jikesrvm.opt.ir.OPT_IR; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.OPT_Constants; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_IR; +import org.jikesrvm.opt.ir.OPT_BasicBlock; // Instructions -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_Operator; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.ALoad; -import com.ibm.jikesrvm.opt.ir.AStore; -import com.ibm.jikesrvm.opt.ir.Athrow; -import com.ibm.jikesrvm.opt.ir.Binary; -import com.ibm.jikesrvm.opt.ir.BBend; -import com.ibm.jikesrvm.opt.ir.Call; -import com.ibm.jikesrvm.opt.ir.CondMove; -import com.ibm.jikesrvm.opt.ir.GetField; -import com.ibm.jikesrvm.opt.ir.Goto; -import com.ibm.jikesrvm.opt.ir.IfCmp; -import com.ibm.jikesrvm.opt.ir.Move; -import com.ibm.jikesrvm.opt.ir.New; -import com.ibm.jikesrvm.opt.ir.LookupSwitch; -import com.ibm.jikesrvm.opt.ir.PutField; -import com.ibm.jikesrvm.opt.ir.Unary; +import org.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_Operator; +import org.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.ALoad; +import org.jikesrvm.opt.ir.AStore; +import org.jikesrvm.opt.ir.Athrow; +import org.jikesrvm.opt.ir.Binary; +import org.jikesrvm.opt.ir.BBend; +import org.jikesrvm.opt.ir.Call; +import org.jikesrvm.opt.ir.CondMove; +import org.jikesrvm.opt.ir.GetField; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.Move; +import org.jikesrvm.opt.ir.New; +import org.jikesrvm.opt.ir.LookupSwitch; +import org.jikesrvm.opt.ir.PutField; +import org.jikesrvm.opt.ir.Unary; // Operands -import com.ibm.jikesrvm.opt.ir.OPT_AddressConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchProfileOperand; -import com.ibm.jikesrvm.opt.ir.OPT_ConditionOperand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_LocationOperand; -import com.ibm.jikesrvm.opt.ir.OPT_MethodOperand; -import com.ibm.jikesrvm.opt.ir.OPT_Operand; -import com.ibm.jikesrvm.opt.ir.OPT_Register; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TrueGuardOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TypeOperand; +import org.jikesrvm.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.opt.ir.OPT_BranchOperand; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_LocationOperand; +import org.jikesrvm.opt.ir.OPT_MethodOperand; +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_Register; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.opt.ir.OPT_TypeOperand; public class X862IR extends DecoderUtils implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { Modified: src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-03-16 15:33:01 UTC (rev 2) @@ -12,13 +12,13 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.Binary; -import com.ibm.jikesrvm.opt.ir.Move; +import org.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.Binary; +import org.jikesrvm.opt.ir.Move; -import com.ibm.jikesrvm.opt.ir.OPT_Operand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; /** * Wrapper for X86 decoded operands that are either in memory, Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-03-16 15:33:01 UTC (rev 2) @@ -19,29 +19,29 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import com.ibm.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.opt.ir.Binary; -import com.ibm.jikesrvm.opt.ir.BooleanCmp; -import com.ibm.jikesrvm.opt.ir.BooleanCmp2; -import com.ibm.jikesrvm.opt.ir.CondMove; -import com.ibm.jikesrvm.opt.ir.IfCmp; -import com.ibm.jikesrvm.opt.ir.Goto; -import com.ibm.jikesrvm.opt.ir.Move; -import com.ibm.jikesrvm.opt.ir.Unary; +import org.jikesrvm.opt.ir.Binary; +import org.jikesrvm.opt.ir.BooleanCmp; +import org.jikesrvm.opt.ir.BooleanCmp2; +import org.jikesrvm.opt.ir.CondMove; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.Move; +import org.jikesrvm.opt.ir.Unary; -import com.ibm.jikesrvm.opt.ir.OPT_Operator; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.OPT_Operator; +import org.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_Operand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchProfileOperand; -import com.ibm.jikesrvm.opt.ir.OPT_ConditionOperand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_BranchOperand; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; /** * Decoder for X86 instructions Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-03-16 15:33:01 UTC (rev 2) @@ -10,8 +10,8 @@ import java.io.*; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-03-16 15:33:01 UTC (rev 2) @@ -19,48 +19,48 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.DBT_Options; -import com.ibm.jikesrvm.VM; +import org.jikesrvm.VM; -import com.ibm.jikesrvm.classloader.VM_Atom; -import com.ibm.jikesrvm.classloader.VM_BootstrapClassLoader; -import com.ibm.jikesrvm.classloader.VM_Class; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_Method; -import com.ibm.jikesrvm.classloader.VM_MethodReference; -import com.ibm.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_BootstrapClassLoader; +import org.jikesrvm.classloader.VM_Class; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.opt.OPT_Constants; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; -import com.ibm.jikesrvm.opt.ir.OPT_IR; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.OPT_Constants; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.opt.ir.OPT_IR; +import org.jikesrvm.opt.ir.OPT_BasicBlock; -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.OPT_Operator; -import com.ibm.jikesrvm.opt.ir.Athrow; -import com.ibm.jikesrvm.opt.ir.BBend; -import com.ibm.jikesrvm.opt.ir.Call; -import com.ibm.jikesrvm.opt.ir.CondMove; -import com.ibm.jikesrvm.opt.ir.Goto; -import com.ibm.jikesrvm.opt.ir.GetField; -import com.ibm.jikesrvm.opt.ir.IfCmp; -import com.ibm.jikesrvm.opt.ir.LookupSwitch; -import com.ibm.jikesrvm.opt.ir.Move; -import com.ibm.jikesrvm.opt.ir.New; -import com.ibm.jikesrvm.opt.ir.PutField; +import org.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.OPT_Operator; +import org.jikesrvm.opt.ir.Athrow; +import org.jikesrvm.opt.ir.BBend; +import org.jikesrvm.opt.ir.Call; +import org.jikesrvm.opt.ir.CondMove; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.GetField; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.LookupSwitch; +import org.jikesrvm.opt.ir.Move; +import org.jikesrvm.opt.ir.New; +import org.jikesrvm.opt.ir.PutField; -import com.ibm.jikesrvm.opt.ir.OPT_Operand; -import com.ibm.jikesrvm.opt.ir.OPT_AddressConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BranchProfileOperand; -import com.ibm.jikesrvm.opt.ir.OPT_ConditionOperand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_MethodOperand; -import com.ibm.jikesrvm.opt.ir.OPT_Register; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TrueGuardOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TypeOperand; +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.opt.ir.OPT_BranchOperand; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_MethodOperand; +import org.jikesrvm.opt.ir.OPT_Register; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.opt.ir.OPT_TypeOperand; /** * A collection of common tools used by decoders. The public entry Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,26 +8,26 @@ */ package org.binarytranslator.generic.memory; -import com.ibm.jikesrvm.VM; -import com.ibm.jikesrvm.classloader.VM_Atom; -import com.ibm.jikesrvm.classloader.VM_BootstrapClassLoader; -import com.ibm.jikesrvm.classloader.VM_FieldReference; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_Method; -import com.ibm.jikesrvm.classloader.VM_MethodReference; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.opt.ir.Call; -import com.ibm.jikesrvm.opt.ir.GetField; -import com.ibm.jikesrvm.opt.ir.Unary; -import com.ibm.jikesrvm.opt.ir.OPT_AddressConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_LocationOperand; -import com.ibm.jikesrvm.opt.ir.OPT_MethodOperand; -import com.ibm.jikesrvm.opt.ir.OPT_Operators; -import com.ibm.jikesrvm.opt.ir.OPT_Register; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.VM; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_BootstrapClassLoader; +import org.jikesrvm.classloader.VM_FieldReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.opt.ir.Call; +import org.jikesrvm.opt.ir.GetField; +import org.jikesrvm.opt.ir.Unary; +import org.jikesrvm.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_LocationOperand; +import org.jikesrvm.opt.ir.OPT_MethodOperand; +import org.jikesrvm.opt.ir.OPT_Operators; +import org.jikesrvm.opt.ir.OPT_Register; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; import org.binarytranslator.generic.decoder.DecoderUtils; /** Modified: src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,24 +8,24 @@ */ package org.binarytranslator.generic.memory; -import com.ibm.jikesrvm.classloader.VM_Atom; -import com.ibm.jikesrvm.classloader.VM_FieldReference; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.opt.ir.ALoad; -import com.ibm.jikesrvm.opt.ir.Binary; -import com.ibm.jikesrvm.opt.ir.GetField; -import com.ibm.jikesrvm.opt.ir.Goto; -import com.ibm.jikesrvm.opt.ir.IfCmp; -import com.ibm.jikesrvm.opt.ir.OPT_AddressConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; -import com.ibm.jikesrvm.opt.ir.OPT_ConditionOperand; -import com.ibm.jikesrvm.opt.ir.OPT_IntConstantOperand; -import com.ibm.jikesrvm.opt.ir.OPT_LocationOperand; -import com.ibm.jikesrvm.opt.ir.OPT_Register; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; -import com.ibm.jikesrvm.opt.ir.OPT_TrueGuardOperand; -import com.ibm.jikesrvm.opt.ir.Unary; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_FieldReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.opt.ir.ALoad; +import org.jikesrvm.opt.ir.Binary; +import org.jikesrvm.opt.ir.GetField; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.opt.ir.OPT_LocationOperand; +import org.jikesrvm.opt.ir.OPT_Register; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.opt.ir.Unary; import java.io.RandomAccessFile; import org.binarytranslator.generic.memory.IntAddressedMemory; import org.binarytranslator.vmInterface.TranslationHelper; Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,7 +8,7 @@ */ package org.binarytranslator.generic.memory; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; import org.binarytranslator.generic.decoder.DecoderUtils; import java.io.RandomAccessFile; Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-16 15:33:01 UTC (rev 2) @@ -11,10 +11,10 @@ import java.util.Hashtable; import java.io.*; -import com.ibm.jikesrvm.VM_CompiledMethod; -import com.ibm.jikesrvm.VM_CodeArray; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.VM_CompiledMethod; +import org.jikesrvm.VM_CodeArray; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.DynamicCodeRunner; Modified: src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2007-03-16 15:33:01 UTC (rev 2) @@ -7,7 +7,7 @@ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 */ package org.binarytranslator.vmInterface; -import com.ibm.jikesrvm.opt.OPT_CompilerPhase; +import org.jikesrvm.opt.OPT_CompilerPhase; /** * The OPT_CompilerPhase which translates from PowerPC machine code Modified: src/org/binarytranslator/vmInterface/DBT_OptimizingCompilerException.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_OptimizingCompilerException.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/vmInterface/DBT_OptimizingCompilerException.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,7 +8,7 @@ */ package org.binarytranslator.vmInterface; -import com.ibm.jikesrvm.opt.OPT_OptimizingCompilerException; +import org.jikesrvm.opt.OPT_OptimizingCompilerException; /** * Use this exception if we encounter a runtime error in the binary translator Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-03-16 15:33:01 UTC (rev 2) @@ -9,17 +9,17 @@ package org.binarytranslator.vmInterface; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; -import com.ibm.jikesrvm.classloader.VM_BootstrapClassLoader; -import com.ibm.jikesrvm.VM_CompiledMethod; -import com.ibm.jikesrvm.VM_CompiledMethods; -import com.ibm.jikesrvm.classloader.VM_NormalMethod; -import com.ibm.jikesrvm.classloader.VM_Class; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.classloader.VM_MemberReference; -import com.ibm.jikesrvm.classloader.VM_Atom; -import com.ibm.jikesrvm.VM_Statics; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.classloader.VM_BootstrapClassLoader; +import org.jikesrvm.VM_CompiledMethod; +import org.jikesrvm.VM_CompiledMethods; +import org.jikesrvm.classloader.VM_NormalMethod; +import org.jikesrvm.classloader.VM_Class; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.VM_Statics; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_HIRGenerator; /** * A method class which can be used in place of a VM_NormalMethod but @@ -84,7 +84,7 @@ public static void configure() { VM_Atom clsDescriptor = VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/vmInterface/DummyDynamicCodeRunner;"); VM_Atom memName = VM_Atom.findOrCreateAsciiAtom("invokeCode"); - invokeCodeDescriptor = VM_Atom.findOrCreateAsciiAtom("(Lcom.ibm.jikesrvm/VM_CodeArray;Lorg/binarytranslator/generic/os/process/ProcessSpace;)I"); + invokeCodeDescriptor = VM_Atom.findOrCreateAsciiAtom("(Lorg/jikesrvm/VM_CodeArray;Lorg/binarytranslator/generic/os/process/ProcessSpace;)I"); VM_TypeReference tRef = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), clsDescriptor); dummyRunnerTypeRef = VM_TypeReference.findOrCreate(VM_BootstrapClassLoader.getBootstrapClassLoader(), Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-03-16 15:33:01 UTC (rev 2) @@ -7,10 +7,10 @@ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 */ package org.binarytranslator.vmInterface; -import com.ibm.jikesrvm.VM; -import com.ibm.jikesrvm.VM_DynamicBridge; -import com.ibm.jikesrvm.VM_CodeArray; -import com.ibm.jikesrvm.VM_Magic; +import org.jikesrvm.VM; +import org.jikesrvm.VM_DynamicBridge; +import org.jikesrvm.VM_CodeArray; +import org.jikesrvm.VM_Magic; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.pragma.NoInlinePragma; import org.binarytranslator.DBT_Options; Modified: src/org/binarytranslator/vmInterface/TranslationHelper.java =================================================================== --- src/org/binarytranslator/vmInterface/TranslationHelper.java 2006-12-07 14:54:50 UTC (rev 1) +++ src/org/binarytranslator/vmInterface/TranslationHelper.java 2007-03-16 15:33:01 UTC (rev 2) @@ -8,13 +8,13 @@ */ package org.binarytranslator.vmInterface; -import com.ibm.jikesrvm.classloader.VM_Method; -import com.ibm.jikesrvm.classloader.VM_TypeReference; -import com.ibm.jikesrvm.opt.ir.OPT_BasicBlock; -import com.ibm.jikesrvm.opt.ir.OPT_BranchProfileOperand; -import com.ibm.jikesrvm.opt.ir.OPT_GenerationContext; -import com.ibm.jikesrvm.opt.ir.OPT_Instruction; -import com.ibm.jikesrvm.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.opt.ir.OPT_BasicBlock; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.opt.ir.OPT_Instruction; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; /** * Translation helper interface This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-03-18 13:35:14
|
Revision: 3 http://svn.sourceforge.net/pearcolator/?rev=3&view=rev Author: captain5050 Date: 2007-03-16 16:59:58 -0700 (Fri, 16 Mar 2007) Log Message: ----------- New build file. More fixed for new build system Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_Registers.java src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Added Paths: ----------- build.xml ext/org/jikesrvm/ppc/ ext/org/jikesrvm/ppc/PPC_Disassembler.java ext/org/jikesrvm/ppc/opcodeXX.java ext/org/jikesrvm/ppc/opcode_tab.java Added: build.xml =================================================================== --- build.xml (rev 0) +++ build.xml 2007-03-16 23:59:58 UTC (rev 3) @@ -0,0 +1,30 @@ +<project name="binarytranslator.org" default="compile" basedir="../.."> + <property name="dbt.java" location="projects/dbt/src"/> + <property name="dbt-ext.java" location="projects/dbt/ext"/> + <target name="compile" depends="compile-external"> + <javac destdir="${build.classes}" + debug="true" + debugLevel="lines,source" + source="1.5" + target="1.5" + srcdir="${dbt.java}"> + <classpath> + <pathelement location="${build.vmmagic-stub.classes}"/> + <pathelement location="${build.classes}"/> + </classpath> + </javac> + </target> + <target name="compile-external"> + <javac destdir="${build.classes}" + debug="true" + debugLevel="lines,source" + source="1.5" + target="1.5" + srcdir="${dbt-ext.java}"> + <classpath> + <pathelement location="${build.vmmagic-stub.classes}"/> + <pathelement location="${build.classes}"/> + </classpath> + </javac> + </target> +</project> \ No newline at end of file Added: ext/org/jikesrvm/ppc/PPC_Disassembler.java =================================================================== --- ext/org/jikesrvm/ppc/PPC_Disassembler.java (rev 0) +++ ext/org/jikesrvm/ppc/PPC_Disassembler.java 2007-03-16 23:59:58 UTC (rev 3) @@ -0,0 +1,1656 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp. 2001 + */ +package org.jikesrvm.ppc; + +/** + * Disassembler for Rios instruction set. + * @author Ton Ngo + * + * Defined: disasm(inst, addr, buf, reg) + * INSTRUCTION inst; Address addr; CHAR *buf; CHAR reg[4][10]; + * + * 31 Jul 1990 Derek Lieber. + * Borrowed from libdbx (opcode.c, decode.c). + * + * 30 Jan 1998 Ton Ngo: + * adapted for Java debugger jdp + * + * 7 Aug 1998 John Whaley: + * rewritten in Java + * + * 26 Jan 1999 Ton Ngo: + * New instruction for PowerPC that are not in the POWER instruction set + * opcode is bit 0-5 of the instruction + * extop is the extended opcode as listed in the manual + * key is extop plus additional bits for variation on an opcode (. or o) + * form is the instruction format: I, B, SC, D, DS, X, XL, XFX, XFL, XO, A, M + * format is a local enumeration to specify how to print the instruction + * (this is specific to each decode_?? method). + * + * 18 Dec 2000 Dave Grove: + * Changed the mnemonics for POWER instructions that have + * different names on the PowerPC to use the PowerPC mnemonic. + * (Applied changes from Appendix F of PPC Architecture book). + * + * mnemonic opcode extop key form format Example + * -------- ------ --- --- ---- ------ -------- + * dcbf 31 86 172 X 6 7C0218AC + * dcbi 31 470 940 X 6 7C021BAC + * dcbst 31 54 108 X 6 7C02186C + * dcbt 31 278 556 X 6 7C021A2C + * dcbtst 31 246 492 X 6 7C0219EC + * dcbz 31 1014 2028 X 6 7C021FEC + * divw 31 491 982 XO 1 7C221BD6 + * divw. 31 491 983 XO 1 7C221BD7 + * divwo 31 491 2006 XO 1 7C221FD6 + * divwo. 31 491 2007 XO 1 7C221FD7 + * divwu 31 459 918 XO 1 7C221B96 + * divwu. 31 459 919 XO 1 7C221B97 + * divwuo 31 459 1942 XO 1 7C221F96 + * divwuo. 31 459 1943 XO 1 7C221F97 + * eieio 31 854 1708 X 1 7C0006AC + * extsb 31 954 1908 X 0 7C220774 + * extsb. 31 954 1909 X 0 7C220775 + * icbi 31 982 1964 X 6 7C021FAC + * lwarx 31 20 40 X 7 7C221828 + * mfsrin 31 659 1318 X 4 7C201526 + * mulhw 31 75 150 XO 1 7C221896 + * mulhw. 31 75 151 XO 1 7C221897 + * mulhwu 31 11 22 XO 1 7C221816 + * mulhwu. 31 11 23 XO 1 7C221817 + * stwcx. 31 150 301 X 7 7C22192D + * subf 31 40 80 XO 1 7C221850 + * subf. 31 40 81 XO 1 7C221851 + * subfo 31 40 1104 XO 1 7C221C50 + * subfo. 31 40 1105 XO 1 7C221C51 + * + * fadds 59 21 42 A 0 EC22182A + * fadds. 59 21 43 A 0 EC22182B + * fdivs 59 18 36 A 0 EC221824 + * fdivs. 59 18 37 A 0 EC221825 + * fmadds 59 29 58 A 2 EC22193A + * fmadds. 59 29 59 A 2 EC22193B + * fmsubs 59 28 56 A 2 EC221938 + * fmsubs. 59 28 57 A 2 EC221939 + * fmuls 59 25 50 A 1 EC2200F2 + * fmuls. 59 25 51 A 1 EC2200F3 + * fnmadds 59 31 62 A 2 EC22193E + * fnmadds. 59 31 63 A 2 EC22193F + * fnmsubs 59 30 60 A 2 EC22193C + * fnmsubs. 59 30 61 A 2 EC22193D + * fsubs 59 20 40 A 0 EC221828 + * fsubs. 59 20 41 A 0 EC221829 + * mfear + * mfpvw + * mfsprg + * mtear + * mtsprg + * mfdbatl + * mfdbatu + * mtdbatl + * mtdbatu + * mttb + * mttbu + * mftb + * mftbu + * mfibatl + * mfibatu + * mtibatl + * mtibatu + * + * 23 Apr 2003 Kris Venstermans: + * Added instruction decoding for 64 bit architecture. + * Use of constant definitions instead of integers. + * Cleaned up some old power instructions. + */ + +public class PPC_Disassembler { + // special register name copied from /usr/include/sys/reg.h + static final int IAR = 128; + static final int MSR = 129; + static final int CR = 130; + static final int LR = 131; + static final int CTR = 132; + static final int XER = 133; + static final int MQ = 134; + static final int TID = 135; + static final int FPSCR = 136; + static final int FPINFO = 138; + static final int FPSCRX = 148; + static final String GPR_NAMES[] = { "R0", "R1", "R2", "R3", "R4", "R5", + "R6", "R7","R8", "R9", "R10", "R11", + "R12", "R13","R14", "R15","R16", "R17", + "R18", "R19", "R20", "R21", "R22", "R23", + "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31" + }; + static final String FPR_NAMES[] = { "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", + "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", + "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", + "F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31" + }; + + // for testing purposes + public static void main(String[] args) { + + int instr = Integer.parseInt(args[0],16); + int addr = Integer.parseInt(args[1],16); + System.out.println("instr = "+intAsHexString(instr)+" addr = "+ + intAsHexString(addr)); + System.out.println("result --> "+disasm(instr, addr)); + + } + + static int bits (int x, int n, int m) { + return ((x >> (31-m)) & ((1 << (m-n+1)) - 1)); + } + + static int signed (int x, int n, int m) { + return ((x << n) >> 31-m+n); + } + + static String rname(int n) { + String rvmName; + if (n>=0 && n<=31) + rvmName = GPR_NAMES[n]; + else if (n>=128 && n<=135) + rvmName = FPR_NAMES[n-128]; + else + switch (n) { + case IAR: rvmName = "IAR"; break; + case MSR: rvmName = "MSR"; break; + case CR: rvmName = "CR"; break; + case LR: rvmName = "LR"; break; + case CTR: rvmName = "CTR"; break; + case XER: rvmName = "XER"; break; + case MQ: rvmName = "MQ"; break; + case TID: rvmName = "TID"; break; + case FPSCR: rvmName = "FPSCR"; break; + case FPINFO: rvmName = "FPINFO"; break; + case FPSCRX: rvmName = "FPSCRX"; break; + default: rvmName = "r" + n; break; + } + return rvmName; + } + + + static final int INST_SZ = 4; + + /* Special register fields */ + static final int SPR_MQ = 0; + static final int SPR_XER = 1; + static final int SPR_LR = 8; + static final int SPR_CTR = 9; + static final int SPR_TID = 17; + static final int SPR_DSISR= 18; + static final int SPR_DAR = 19; + static final int SPR_RTCU = 20; + static final int SPR_RTCL = 21; + static final int SPR_DEC = 22; + static final int SPR_SDR0 = 24; + static final int SPR_SDR1 = 25; + static final int SPR_SRR0 = 26; + static final int SPR_SRR1 = 27; + + /* Trap Options */ + static final int TO_LT=16; + static final int TO_GT= 8; + static final int TO_EQ= 4; + static final int TO_LLT= 2; + static final int TO_LGT= 1; + + /* Different instruction formats */ + + static final int D_FORM = 0; + static final int B_FORM = 1; + static final int I_FORM= 2; + static final int SC_FORM = 3; + static final int X_FORM = 4; + static final int XL_FORM = 5; + static final int XFX_FORM = 6; + static final int XFL_FORM = 7; + static final int XO_FORM = 8; + static final int A_FORM = 9; + static final int M_FORM =10; + static final int DS_FORM =30; + static final int XS_FORM =31; + static final int MD_FORM =32; + static final int MDS_FORM =33; + + static final int EXTENDED =11; + static final int INVALID_OP=12; + + /* Condition register fields */ + static final int CR_LT=8; + static final int CR_GT=4; + static final int CR_EQ=2; + static final int CR_SO=1; + + static final int X=9; // place holder + + /* + * Instruction decoder. + */ + static int destination; + + static int[] opcode_to_form = { + /* table to convert opcode into */ + /* instruction formats */ + + /* FORM */ + INVALID_OP, /* OPCODE 00 */ + INVALID_OP, /* OPCODE 01 */ + D_FORM, /* OPCODE 02 */ + D_FORM, /* OPCODE 03 */ + D_FORM, /* OPCODE 04 */ + D_FORM, /* OPCODE 05 */ + D_FORM, /* OPCODE 06 */ + D_FORM, /* OPCODE 07 */ + D_FORM, /* OPCODE 08 */ + D_FORM, /* OPCODE 09 */ + D_FORM, /* OPCODE 10 */ + D_FORM, /* OPCODE 11 */ + D_FORM, /* OPCODE 12 */ + D_FORM, /* OPCODE 13 */ + D_FORM, /* OPCODE 14 */ + D_FORM, /* OPCODE 15 */ + B_FORM, /* OPCODE 16 */ + SC_FORM, /* OPCODE 17 */ + I_FORM, /* OPCODE 18 */ + XL_FORM, /* OPCODE 19 */ + M_FORM, /* OPCODE 20 */ + M_FORM, /* OPCODE 21 */ + M_FORM, /* OPCODE 22 */ + M_FORM, /* OPCODE 23 */ + D_FORM, /* OPCODE 24 */ + D_FORM, /* OPCODE 25 */ + D_FORM, /* OPCODE 26 */ + D_FORM, /* OPCODE 27 */ + D_FORM, /* OPCODE 28 */ + D_FORM, /* OPCODE 29 */ + EXTENDED, /* OPCODE 30 */ + EXTENDED, /* OPCODE 31 */ + D_FORM, /* OPCODE 32 */ + D_FORM, /* OPCODE 33 */ + D_FORM, /* OPCODE 34 */ + D_FORM, /* OPCODE 35 */ + D_FORM, /* OPCODE 36 */ + D_FORM, /* OPCODE 37 */ + D_FORM, /* OPCODE 38 */ + D_FORM, /* OPCODE 39 */ + D_FORM, /* OPCODE 40 */ + D_FORM, /* OPCODE 41 */ + D_FORM, /* OPCODE 42 */ + D_FORM, /* OPCODE 43 */ + D_FORM, /* OPCODE 44 */ + D_FORM, /* OPCODE 45 */ + D_FORM, /* OPCODE 46 */ + D_FORM, /* OPCODE 47 */ + D_FORM, /* OPCODE 48 */ + D_FORM, /* OPCODE 49 */ + D_FORM, /* OPCODE 50 */ + D_FORM, /* OPCODE 51 */ + D_FORM, /* OPCODE 52 */ + D_FORM, /* OPCODE 53 */ + D_FORM, /* OPCODE 54 */ + D_FORM, /* OPCODE 55 */ + INVALID_OP, /* OPCODE 56 */ + INVALID_OP, /* OPCODE 57 */ + DS_FORM, /* OPCODE 58 */ + A_FORM, /* OPCODE 59 */ + INVALID_OP, /* OPCODE 60 */ + INVALID_OP, /* OPCODE 61 */ + DS_FORM, /* OPCODE 62 */ + EXTENDED /* OPCODE 63 */ + }; + + static opcode_tab[] Dform = { + + /* Table for the D instruction format */ + + /* OPCD EO format mnemonic */ + /* ---- -- ------ -------- */ + /* 0, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 1, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 2, XXX, */ new opcode_tab ( 3, "tdi"), + /* 3, XXX, */ new opcode_tab ( 3, "twi" ), + /* 4, XXX, */ new opcode_tab ( X, "RESERVED"), + + /* 5, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 6, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 7, XXX, */ new opcode_tab ( 0, "mulli" ), + /* 8, XXX, */ new opcode_tab ( 0, "subfic" ), + /* 9, XXX, */ new opcode_tab ( X, "RESERVED"), + + /* 10, XXX, */ new opcode_tab ( 4, "cmpli" ), + /* 11, XXX, */ new opcode_tab ( 4, "cmpi" ), + /* 12, XXX, */ new opcode_tab ( 0, "addic" ), + /* 13, XXX, */ new opcode_tab ( 0, "addic." ), + /* 14, XXX, */ new opcode_tab ( 2, "addi" ), + + /* 15, XXX, */ new opcode_tab ( 0, "addis" ), + /* 16, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 17, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 18, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 19, XXX, */ new opcode_tab ( X, "RESERVED"), + + /* 20, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 21, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 22, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 23, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 24, XXX, */ new opcode_tab ( 1, "ori" ), + + /* 25, XXX, */ new opcode_tab ( 1, "oris" ), + /* 26, XXX, */ new opcode_tab ( 1, "xori" ), + /* 27, XXX, */ new opcode_tab ( 1, "xoris" ), + /* 28, XXX, */ new opcode_tab ( 1, "andi. " ), + /* 29, XXX, */ new opcode_tab ( 1, "andis." ), + + /* 30, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 31, XXX, */ new opcode_tab ( X, "RESERVED"), + /* 32, XXX, */ new opcode_tab ( 2, "lwz" ), + /* 33, XXX, */ new opcode_tab ( 2, "lwzu" ), + /* 34, XXX, */ new opcode_tab ( 2, "lbz" ), + + /* 35, XXX, */ new opcode_tab ( 2, "lbzu" ), + /* 36, XXX, */ new opcode_tab ( 2, "stw" ), + /* 37, XXX, */ new opcode_tab ( 2, "stwu" ), + /* 38, XXX, */ new opcode_tab ( 2, "stb" ), + /* 39, XXX, */ new opcode_tab ( 2, "stbu" ), + + /* 40, XXX, */ new opcode_tab ( 2, "lhz" ), + /* 41, XXX, */ new opcode_tab ( 2, "lhzu" ), + /* 42, XXX, */ new opcode_tab ( 2, "lha" ), + /* 43, XXX, */ new opcode_tab ( 2, "lhau" ), + /* 44, XXX, */ new opcode_tab ( 2, "sth" ), + + /* 45, XXX, */ new opcode_tab ( 2, "sthu" ), + /* 46, XXX, */ new opcode_tab ( 2, "lmw" ), + /* 47, XXX, */ new opcode_tab ( 2, "stmw" ), + /* 48, XXX, */ new opcode_tab ( 5, "lfs" ), + /* 49, XXX, */ new opcode_tab ( 5, "lfsu" ), + + /* 50, XXX, */ new opcode_tab ( 5, "lfd" ), + /* 51, XXX, */ new opcode_tab ( 5, "lfdu" ), + /* 52, XXX, */ new opcode_tab ( 5, "stfs" ), + /* 53, XXX, */ new opcode_tab ( 5, "stfsu" ), + /* 54, XXX, */ new opcode_tab ( 5, "stfd" ), + + /* 55, XXX, */ new opcode_tab ( 5, "stfdu" ) + }; + + + static opcode_tab[] XLform = { + + /* Table for the XL instruction format */ + + /* OPCD EO format mnemonic */ + /* ---- -- ------ -------- */ + /* 19, 0, */ new opcode_tab( 2, "mcrf" ), + /* 19, 16, */ new opcode_tab( 1, "bclr or bclrl"), + /* 19, 33, */ new opcode_tab( 3, "crnor" ), + /* 19, 50, */ new opcode_tab( 0, "rfi" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 129, */ new opcode_tab( 3, "crandc" ), + /* 19, 150, */ new opcode_tab( 0, "isync" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 193, */ new opcode_tab( 3, "crxor" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 225, */ new opcode_tab( 3, "crnand" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 257, */ new opcode_tab( 3, "crand" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 289, */ new opcode_tab( 3, "creqv" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 417, */ new opcode_tab( 3, "crorc" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 449, */ new opcode_tab( 3, "cror" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, XXX, */ new opcode_tab( X, "RESERVED" ), + /* 19, 528, */ new opcode_tab( 1, "bcctr or bcctrl") + }; + + + + /** + * Opcode 30 table: + * The key is bits 27 through 30 of the instruction. + * "Form" is the instruction format: + * I, B, SC, D, DS, X, XL, XFX, XFL, XO, A, M, MDS, MD + * "format" is how the instruction should be printed (specific to the disassembler) + */ + + static opcodeXX[] opcode30 = { + + /* key form format mnemonic */ + /* --- ---- ------ -------- */ + new opcodeXX( 0, MD_FORM, 0, "rldicl" ), + new opcodeXX( 1, MD_FORM, 0, "rldicl" ), + new opcodeXX( 2, MD_FORM, 1, "rldicr" ), + new opcodeXX( 3, MD_FORM, 1, "rldicr" ), + new opcodeXX( 4, MD_FORM, 0, "rldic" ), + new opcodeXX( 5, MD_FORM, 0, "rldic" ), + new opcodeXX( 6, MD_FORM, 0, "rldimi" ), + new opcodeXX( 7, MD_FORM, 0, "rldimi" ), + new opcodeXX( 8, MDS_FORM, 0, "rldcl" ), + new opcodeXX( 9, MDS_FORM, 1, "rldcr" ) + }; + + + /** + * Opcode 31 table: + * The key is bits 21 through 31 of the instruction. + * "Form" is the instruction format: + * I, B, SC, D, DS, X, XL, XFX, XFL, XO, A, M + * "format" is how the instruction should be printed (specific to the disassembler) + */ + + + static opcodeXX[] opcode31 = { + + /* key form format mnemonic */ + /* --- ---- ------ -------- */ + new opcodeXX( 0, X_FORM, 22, "cmp"), + new opcodeXX( 8, X_FORM, 24, "tw"), + new opcodeXX( 16, XO_FORM, 1, "subfc"), + new opcodeXX( 17, XO_FORM, 1, "subfc."), + new opcodeXX( 20, XO_FORM, 1, "addc"), + new opcodeXX( 21, XO_FORM, 1, "addc."), + new opcodeXX( 38, X_FORM, 2, "mfcr"), + new opcodeXX( 46, X_FORM, 7, "lwzx"), + new opcodeXX( 48, X_FORM, 8, "slw"), + new opcodeXX( 49, X_FORM, 8, "slw."), + new opcodeXX( 52, X_FORM, 9, "cntlzw"), + new opcodeXX( 53, X_FORM, 9, "cntlzw."), + new opcodeXX( 56, X_FORM, 8, "and"), + new opcodeXX( 57, X_FORM, 8, "and."), + new opcodeXX( 64, X_FORM, 22, "cmpl"), + new opcodeXX( 110, X_FORM, 7, "lwzux"), + new opcodeXX( 120, X_FORM, 8, "andc"), + new opcodeXX( 121, X_FORM, 8, "andc."), + new opcodeXX( 166, X_FORM, 2, "mfmsr"), + new opcodeXX( 174, X_FORM, 7, "lbzx"), + new opcodeXX( 208, XO_FORM, 0, "neg"), + new opcodeXX( 209, XO_FORM, 0, "neg."), + new opcodeXX( 238, X_FORM, 7, "lbzux"), + new opcodeXX( 248, X_FORM, 8, "nor"), + new opcodeXX( 249, X_FORM, 8, "nor."), + new opcodeXX( 272, XO_FORM, 1, "subfe"), + new opcodeXX( 273, XO_FORM, 1, "subfe."), + new opcodeXX( 276, XO_FORM, 1, "adde"), + new opcodeXX( 277, XO_FORM, 1, "adde."), + new opcodeXX( 288, XFX_FORM, 9, "mtcrf"), + new opcodeXX( 292, X_FORM, 2, "mtmsr"), + new opcodeXX( 302, X_FORM, 7, "stwx"), + new opcodeXX( 366, X_FORM, 7, "stwux"), + new opcodeXX( 400, XO_FORM, 0, "subfze"), + new opcodeXX( 401, XO_FORM, 0, "subfze."), + new opcodeXX( 404, XO_FORM, 0, "addze"), + new opcodeXX( 405, XO_FORM, 0, "addze."), + new opcodeXX( 430, X_FORM, 7, "stbx"), + new opcodeXX( 464, XO_FORM, 0, "subfme"), + new opcodeXX( 465, XO_FORM, 0, "subfme."), + new opcodeXX( 468, XO_FORM, 0, "addme"), + new opcodeXX( 469, XO_FORM, 0, "addme."), + new opcodeXX( 470, XO_FORM, 1, "mullw"), + new opcodeXX( 471, XO_FORM, 1, "mullw."), + new opcodeXX( 494, X_FORM, 7, "stbux"), + new opcodeXX( 532, XO_FORM, 1, "add"), + new opcodeXX( 533, XO_FORM, 1, "add."), + new opcodeXX( 558, X_FORM, 7, "lhzx"), + new opcodeXX( 568, X_FORM, 8, "eqv"), + new opcodeXX( 569, X_FORM, 8, "eqv."), + new opcodeXX( 612, X_FORM, 6, "tlbie"), + new opcodeXX( 622, X_FORM, 7, "lhzux"), + new opcodeXX( 632, X_FORM, 8, "xor"), + new opcodeXX( 633, X_FORM, 8, "xor."), + new opcodeXX( 678, X_FORM, 3, "mfspr"), + new opcodeXX( 686, X_FORM, 7, "lhax"), + new opcodeXX( 750, X_FORM, 7, "lhaux"), + new opcodeXX( 814, X_FORM, 7, "sthx"), + new opcodeXX( 824, X_FORM, 8, "orc"), + new opcodeXX( 825, X_FORM, 8, "orc."), + new opcodeXX( 878, X_FORM, 7, "sthux"), + new opcodeXX( 888, X_FORM, 8, "or"), + new opcodeXX( 889, X_FORM, 8, "or."), + new opcodeXX( 934, X_FORM, 3, "mtspr"), + new opcodeXX( 952, X_FORM, 8, "nand"), + new opcodeXX( 953, X_FORM, 8, "nand."), + new opcodeXX( 1024, X_FORM, 23, "mcrxr"), + new opcodeXX( 1040, XO_FORM, 1, "subfco"), + new opcodeXX( 1041, XO_FORM, 1, "subfco."), + new opcodeXX( 1044, XO_FORM, 1, "addco"), + new opcodeXX( 1045, XO_FORM, 1, "addco."), + new opcodeXX( 1066, X_FORM, 7, "lswx"), + new opcodeXX( 1068, X_FORM, 7, "lwbrx"), + new opcodeXX( 1070, X_FORM, 12, "lfsx"), + new opcodeXX( 1072, X_FORM, 8, "srw"), + new opcodeXX( 1073, X_FORM, 8, "srw."), + new opcodeXX( 1134, X_FORM, 12, "lfsux"), + new opcodeXX( 1194, X_FORM, 10, "lswi"), + new opcodeXX( 1196, X_FORM, 1, "sync"), + new opcodeXX( 1198, X_FORM, 12, "lfdx"), + new opcodeXX( 1262, X_FORM, 12, "lfdux"), + new opcodeXX( 1232, XO_FORM, 0, "nego"), + new opcodeXX( 1233, XO_FORM, 0, "nego."), + new opcodeXX( 1296, XO_FORM, 1, "subfeo"), + new opcodeXX( 1297, XO_FORM, 1, "subfeo."), + new opcodeXX( 1300, XO_FORM, 1, "addeo"), + new opcodeXX( 1301, XO_FORM, 1, "addeo."), + new opcodeXX( 1322, X_FORM, 7, "stswx"), + new opcodeXX( 1324, X_FORM, 7, "stwbrx"), + new opcodeXX( 1326, X_FORM, 12, "stfsx"), + new opcodeXX( 1390, X_FORM, 12, "stfsux"), + new opcodeXX( 1424, XO_FORM, 0, "subfzeo"), + new opcodeXX( 1425, XO_FORM, 0, "subfzeo."), + new opcodeXX( 1428, XO_FORM, 0, "addzeo."), + new opcodeXX( 1429, XO_FORM, 0, "addzeo."), + new opcodeXX( 1450, X_FORM, 10, "stswi"), + new opcodeXX( 1454, X_FORM, 12, "stfdx"), + new opcodeXX( 1488, XO_FORM, 0, "subfmeo."), + new opcodeXX( 1489, XO_FORM, 0, "subfmeo."), + new opcodeXX( 1492, XO_FORM, 0, "addmeo"), + new opcodeXX( 1493, XO_FORM, 0, "addmeo."), + new opcodeXX( 1494, XO_FORM, 1, "mullwo."), + new opcodeXX( 1495, XO_FORM, 1, "mullwo."), + new opcodeXX( 1518, X_FORM, 12, "stfdux"), + new opcodeXX( 1556, XO_FORM, 1, "addo"), + new opcodeXX( 1557, XO_FORM, 1, "addo."), + new opcodeXX( 1580, X_FORM, 7, "lhbrx"), + new opcodeXX( 1584, X_FORM, 8, "sraw"), + new opcodeXX( 1585, X_FORM, 8, "sraw."), + new opcodeXX( 1648, X_FORM, 11, "srawi"), + new opcodeXX( 1649, X_FORM, 11, "srawi."), + new opcodeXX( 1836, X_FORM, 7, "sthbrx"), + new opcodeXX( 1844, X_FORM, 9, "extsh"), + new opcodeXX( 1845, X_FORM, 9, "extsh."), + new opcodeXX( 2028, X_FORM, 6, "dcbz"), + + // these are the addition for the PowerPC + new opcodeXX( 172, X_FORM, 6, "dcbf"), + new opcodeXX( 940, X_FORM, 6, "dcbi"), + new opcodeXX( 108, X_FORM, 6, "dcbst"), + new opcodeXX( 556, X_FORM, 6, "dcbt"), + new opcodeXX( 492, X_FORM, 6, "dcbtst"), + new opcodeXX( 982, XO_FORM, 1, "divw"), + new opcodeXX( 983, XO_FORM, 1, "divw."), + new opcodeXX( 2006, XO_FORM, 1, "divwo"), + new opcodeXX( 2007, XO_FORM, 1, "divwo."), + new opcodeXX( 918, XO_FORM, 1, "divwu"), + new opcodeXX( 919, XO_FORM, 1, "divwu."), + new opcodeXX( 1942, XO_FORM, 1, "divwuo"), + new opcodeXX( 1943, XO_FORM, 1, "divwuo."), + new opcodeXX( 1708, X_FORM, 1, "eieio"), + new opcodeXX( 1908, X_FORM, 0, "extsb"), + new opcodeXX( 1909, X_FORM, 0, "extsb."), + new opcodeXX( 1964, X_FORM, 6, "icbi"), + new opcodeXX( 40, X_FORM, 7, "lwarx"), + new opcodeXX( 150, XO_FORM, 1, "mulhw"), + new opcodeXX( 151, XO_FORM, 1, "mulhw."), + new opcodeXX( 22, XO_FORM, 1, "mulhwu"), + new opcodeXX( 23, XO_FORM, 1, "mulhwu."), + new opcodeXX( 301, X_FORM, 7, "stwcx."), + new opcodeXX( 80, XO_FORM, 1, "subf"), + new opcodeXX( 81, XO_FORM, 1, "subf."), + new opcodeXX( 1104, XO_FORM, 1, "subfo"), + new opcodeXX( 1105, XO_FORM, 1, "subfo."), + +// these are only valid for 32 bit architecture + new opcodeXX( 420, X_FORM, 17, "mtsr"), + new opcodeXX( 484, X_FORM, 7, "mtsrin"), + new opcodeXX( 1190, X_FORM, 18, "mfsr"), + new opcodeXX( 1318, X_FORM, 4, "mfsrin"), + +// these are the addition for the 64 bit specific instructions + new opcodeXX( 18, XO_FORM, 2, "mulhdu"), + new opcodeXX( 19, XO_FORM, 2, "mulhdu."), + new opcodeXX( 42, X_FORM, 7, "ldx"), + new opcodeXX( 43, X_FORM, 7, "ldx."), + new opcodeXX( 54, X_FORM, 8, "sld"), + new opcodeXX( 55, X_FORM, 8, "sld."), + new opcodeXX( 106, X_FORM, 7, "ldux"), + new opcodeXX( 107, X_FORM, 7, "ldux."), + new opcodeXX( 116, X_FORM, 9, "cntlzd"), + new opcodeXX( 117, X_FORM, 9, "cntlzd."), + new opcodeXX( 136, X_FORM, 24, "td"), + new opcodeXX( 146, XO_FORM, 1, "mulhd"), + new opcodeXX( 151, XO_FORM, 1, "mulhd."), + new opcodeXX( 168, X_FORM, 7, "ldarx"), + new opcodeXX( 298, X_FORM, 7, "stdx"), + new opcodeXX( 362, X_FORM, 7, "stdux"), + new opcodeXX( 429, X_FORM, 7, "stdcx."), + new opcodeXX( 466, XO_FORM, 1, "mulld"), + new opcodeXX( 467, XO_FORM, 1, "mulld."), + new opcodeXX( 682, X_FORM, 7, "lwax"), + new opcodeXX( 746, X_FORM, 7, "lwaux"), + new opcodeXX( 1652, XS_FORM, 0, "sradi"), + new opcodeXX( 1653, XS_FORM, 0, "sradi."), + new opcodeXX( 1654, XS_FORM, 0, "sradi"), + new opcodeXX( 1655, XS_FORM, 0, "sradi."), + new opcodeXX( 868, X_FORM, 6, "slbie"), + new opcodeXX( 914, XO_FORM, 1, "divdu"), + new opcodeXX( 915, XO_FORM, 1, "divdu."), + new opcodeXX( 978, XO_FORM, 1, "divd"), + new opcodeXX( 979, XO_FORM, 1, "divd."), + new opcodeXX( 996, X_FORM, 1, "slbia"), + new opcodeXX( 1078, X_FORM, 8, "srd"), + new opcodeXX( 1079, X_FORM, 8, "srd."), + new opcodeXX( 1588, X_FORM, 8, "srad"), + new opcodeXX( 1589, X_FORM, 8, "srad."), + new opcodeXX( 1972, X_FORM, 9, "extsw"), + new opcodeXX( 1973, X_FORM, 9, "extsw.") + }; + + static opcode_tab[] opcode58 = { + /* Table for the instruction format of opcode 58*/ + + /* EO format mnemonic */ + /* ---- ------ -------- */ + /* 0, */ new opcode_tab ( 0, "ld"), + /* 1, */ new opcode_tab ( 0, "ldu"), + /* 2, */ new opcode_tab ( 0, "lwa"), + /* 3, */ new opcode_tab ( X, "RESERVED") + }; + + static opcode_tab[] opcode62 = { + /* Table for the instruction format of opcode 58*/ + + /* EO format mnemonic */ + /* ---- ------ -------- */ + /* 0, */ new opcode_tab ( 1, "std"), + /* 1, */ new opcode_tab ( 1, "stdu"), + /* 2, */ new opcode_tab ( X, "RESERVED"), + /* 3, */ new opcode_tab ( X, "RESERVED") + }; + +/* Opcode 63 table: The key is computed by taking + * bits 21 through 31 of the instruction. "Form" is + * the instruction format and "format" is how the + * instruction should be printed. */ + + static opcodeXX[] opcode63 = { + + /* key form format mnemonic */ + /* --- ---- ------ -------- */ + new opcodeXX( 0, X_FORM, 19, "fcmpu"), + new opcodeXX( 24, X_FORM, 21, "frsp"), + new opcodeXX( 25, X_FORM, 21, "frsp."), + new opcodeXX( 28, X_FORM, 21, "fctiw"), + new opcodeXX( 29, X_FORM, 21, "fctiw."), + new opcodeXX( 30, X_FORM, 21, "fctiwz"), + new opcodeXX( 31, X_FORM, 21, "fctiwz."), + new opcodeXX( 64, X_FORM, 19, "fcmpo"), + new opcodeXX( 76, X_FORM, 16, "mtfsb1"), + new opcodeXX( 77, X_FORM, 16, "mtfsb1."), + new opcodeXX( 80, X_FORM, 21, "fneg"), + new opcodeXX( 81, X_FORM, 21, "fneg."), + new opcodeXX( 128, X_FORM, 14, "mcrfs"), + new opcodeXX( 140, X_FORM, 16, "mtfsb0"), + new opcodeXX( 141, X_FORM, 16, "mtfsb0."), + new opcodeXX( 144, X_FORM, 21, "fmr"), + new opcodeXX( 145, X_FORM, 21, "fmr."), + new opcodeXX( 268, X_FORM, 15, "mtfsfi"), + new opcodeXX( 269, X_FORM, 15, "mtfsfi."), + new opcodeXX( 272, X_FORM, 21, "fnabs"), + new opcodeXX( 273, X_FORM, 21, "fnabs."), + new opcodeXX( 528, X_FORM, 21, "fabs"), + new opcodeXX( 529, X_FORM, 21, "fabs."), + new opcodeXX( 1166, X_FORM, 13, "mffs"), + new opcodeXX( 1167, X_FORM, 13, "mffs."), + new opcodeXX( 1422, XFL_FORM, 9, "mtfsf"), + new opcodeXX( 1423, XFL_FORM, 9, "mtfsf."), + + // these are only valid for 32 bit architecture + new opcodeXX( 1628, X_FORM, 21, "fctid"), + new opcodeXX( 1629, X_FORM, 21, "fctid."), + new opcodeXX( 1630, X_FORM, 21, "fctidz"), + new opcodeXX( 1631, X_FORM, 21, "fctidz."), + new opcodeXX( 1692, X_FORM, 21, "fcfid"), + new opcodeXX( 1693, X_FORM, 21, "fcfid.") + }; + + static opcodeXX[] opcode59 = { + + /* opcode59 table: These are the addition for the PowerPC set + * Key is bits 26 through 31 of the instruction. + * "Form" is the instruction format and "format" is how the + * instruction should be printed (the enumeration is specific + * to each decode method) + */ + + /* key form format mnemonic */ + new opcodeXX( 42, A_FORM, 0, "fadds"), + new opcodeXX( 43, A_FORM, 0, "fadds."), + new opcodeXX( 36, A_FORM, 0, "fdivs"), + new opcodeXX( 37, A_FORM, 0, "fdivs."), + new opcodeXX( 58, A_FORM, 2, "fmadds"), + new opcodeXX( 59, A_FORM, 2, "fmadds."), + new opcodeXX( 56, A_FORM, 2, "fmsubs"), + new opcodeXX( 57, A_FORM, 2, "fmsubs."), + new opcodeXX( 50, A_FORM, 1, "fmuls"), + new opcodeXX( 51, A_FORM, 1, "fmuls."), + new opcodeXX( 62, A_FORM, 2, "fnmadds"), + new opcodeXX( 63, A_FORM, 2, "fnmadds."), + new opcodeXX( 60, A_FORM, 2, "fnmsubs"), + new opcodeXX( 61, A_FORM, 2, "fnmsubs."), + new opcodeXX( 40, A_FORM, 0, "fsubs"), + new opcodeXX( 41, A_FORM, 0, "fsubs.") + }; + + static opcodeXX[] Aform = { + + /* Aform table: The key is computed by taking + * bits 26 through 31 of the instruction. "Form" is + * the instruction format and "format" is how the + * instruction should be printed. */ + + /* key form format mnemonic */ + new opcodeXX( 36, A_FORM, 0, "fdiv"), + new opcodeXX( 37, A_FORM, 0, "fdiv."), + new opcodeXX( 40, A_FORM, 0, "fsub"), + new opcodeXX( 41, A_FORM, 0, "fsub."), + new opcodeXX( 42, A_FORM, 0, "fadd"), + new opcodeXX( 43, A_FORM, 0, "fadd."), + new opcodeXX( 50, A_FORM, 1, "fm"), + new opcodeXX( 51, A_FORM, 1, "fm."), + new opcodeXX( 56, A_FORM, 2, "fmsub"), + new opcodeXX( 57, A_FORM, 2, "fmsub."), + new opcodeXX( 58, A_FORM, 2, "fmadd"), + new opcodeXX( 59, A_FORM, 2, "fmadd."), + new opcodeXX( 60, A_FORM, 2, "fnmsub"), + new opcodeXX( 61, A_FORM, 2, "fnmsub."), + new opcodeXX( 62, A_FORM, 2, "fnmadd"), + new opcodeXX( 63, A_FORM, 2, "fnmadd.") + }; + + /* + * SPR_name - common special purpose register names options + */ + static String SPR_name(int SPR) + { + switch (SPR) { + case SPR_MQ: return("mq"); + case SPR_XER: return("xer"); + case SPR_LR: return("lr"); + case SPR_CTR: return("ctr"); + case SPR_TID: return("tid"); + case SPR_DSISR: return("dsisr"); + case SPR_DAR: return("dar"); + case SPR_RTCU: return("rtcu"); + case SPR_RTCL: return("rtcu"); + case SPR_DEC: return("dec"); + case SPR_SDR0: return("sdr0"); + case SPR_SDR1: return("sdr1"); + case SPR_SRR0: return("srr0"); + case SPR_SRR1: return("srr1"); + default: return null; + } + } + + /* + * TO_ext - common trap options + */ + static String TO_ext(int TO) + { + switch (TO) { + case TO_LT: return("lt"); + case (TO_LT | TO_EQ): return("le"); + case (TO_LT | TO_GT): return("ne"); + case TO_GT: return("gt"); + case (TO_GT | TO_EQ): return("ge"); + case TO_LLT: return("llt"); + case (TO_LLT | TO_EQ): return("lle"); + case (TO_LLT | TO_LGT): return("lne"); + case TO_LGT: return("lgt"); + case (TO_LGT | TO_EQ): return("lge"); + case TO_EQ: return("eq"); + default:return null; + } + } + + /* + * Translate an instruction from its + * numeric form into something more + * readable. + */ + + public static String disasm(int inst, int addr) + { + int opcode; + int form; + + opcode = bits(inst,0,5); /* Determine opcode */ + form = opcode_to_form[opcode]; /* Determine instruction format */ + + switch(form) /* decode known instruction format */ + { + case D_FORM: + return decode_Dform(inst, opcode); + case DS_FORM: + return decode_DSform(inst, opcode); + case B_FORM: + return decode_Bform(addr, inst, opcode); + case I_FORM: + return decode_Iform(addr,inst, opcode); + case SC_FORM: + return decode_SCform(inst, opcode); + case XL_FORM: + return decode_XLform(inst, opcode); + case M_FORM: + return decode_Mform(inst, opcode); + case A_FORM: + return decode_opcode59(inst); + case EXTENDED: /* More work to do... */ + switch(opcode) /* Switch off of opcode and process from there */ + { + case 30: + return decode_opcode30(inst); + case 31: + return decode_opcode31(inst); + case 63: + return decode_opcode63(inst); + default: + return " Invalid opcode"; + } + case INVALID_OP: /* More work to do... */ + default: + return " Invalid opcode"; + } + } + + /* Decode the D instruction format */ + + static String decode_Dform(int inst, int opcode) + { + int rt, RA, TO, BF, FRT,ufield; + int sfield; + opcode_tab opcode_info; + String datafield, mnemonic, asm_mnemonic, common_opt; + + rt = TO = FRT = bits(inst, 6, 10); + RA = bits(inst, 11, 15); + BF = bits(inst,6,8); + ufield = inst & 0xffff; + sfield = (inst << 16) >> 16; + if (sfield < 0) { + datafield = ""+sfield; + } else { + datafield = intAsHexString(sfield); + } + opcode_info = Dform[opcode]; + mnemonic = opcode_info.mnemonic; + + switch(opcode_info.format) + { + case 0: + if (opcode != 15) { + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RA)+","+datafield; + } else { + if (RA != 0) { + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RA)+","+intAsHexString(ufield); + } else { + return " liu "+ + rname(rt)+","+intAsHexString(ufield); + } + } + case 1: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(rt)+","+intAsHexString(ufield); + case 2: + if ((opcode == 14) && (RA == 0)) { + return " lil" + + " "+rname(rt)+","+datafield; + } else { + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+datafield+"("+rname(RA)+")"; + } + case 3: /* Trap immediate */ + common_opt = TO_ext(TO); + asm_mnemonic = ((opcode == 2) ? "td" : "tw")+common_opt+"i"; + if (common_opt!=null) { + return " ".substring(asm_mnemonic.length()) + asm_mnemonic + + " "+rname(RA)+","+datafield; + } else { + return " ".substring(mnemonic.length()) + mnemonic + + " "+TO+","+rname(RA)+","+datafield; + } + case 4: + int L = inst & 0x00200000; + if (opcode == 11) { + return " ".substring(mnemonic.length()) + mnemonic + ((L==0)?"W":"D") + + " cr"+BF+","+rname(RA)+","+datafield; + } else { + return " ".substring(mnemonic.length()) + mnemonic + ((L==0)?"W":"D") + + " cr"+BF+","+rname(RA)+","+ufield; + } + case 5: + return " ".substring(mnemonic.length()) + mnemonic + + " fr"+FRT+","+rname(RA)+","+datafield; + default: + return " Invalid opcode"; + } + } + + /* Decode the DS instruction format */ + + static String decode_DSform(int inst, int opcode) + { + int XO, RT, RA, sfield; + String datafield, mnemonic; + + XO = bits(inst,30,31); + RT = bits(inst,6,10); + RA = bits(inst,11,15); + sfield = (((inst) & 0xfffc) << 16) >> 16; + datafield = intAsHexString(sfield); + + switch(opcode) { + case 58: + mnemonic = opcode58[XO].mnemonic; + if (mnemonic == "RESERVED") return " Invalid opcode"; + return " ".substring(mnemonic.length()) + mnemonic + + " " + rname(RT)+ ", "+ datafield + "(" + rname(RA) + ")"; + case 62: + mnemonic = opcode62[XO].mnemonic; + if (mnemonic == "RESERVED") return " Invalid opcode"; + return " ".substring(mnemonic.length()) + mnemonic + + " " + rname(RT)+ ", "+ datafield + "(" + rname(RA) + ")"; + default: + return " Invalid opcode"; + } + } + + /* Decode the B instruction format */ + + static String decode_Bform(int addr, int inst, int opcode) + { + int AA, LK, BO, BI; + String mnemonic; + int cr_field; + int target; + + AA = bits(inst,30,30); + LK = bits(inst,31,31); + BO = bits(inst,6,10); + BI = bits(inst,11,15); + target = (((inst) & 0xfffc) << 16) >> 16; + if (AA == 0) + target += addr; + mnemonic = build_branch_op(BO,1 << (3 - (BI&3)),LK,AA,0); + destination = target; + cr_field = (BI>>2); + /* Build disassembly without target, added on later... */ + if (cr_field != 0) {/* Not CR 0 ? */ + return " ".substring(mnemonic.length()) + mnemonic + + " "+cr_field + " " + Integer.toHexString(destination); + } else { + return " ".substring(mnemonic.length()) + mnemonic + + " " + Integer.toHexString(destination); + } + } + + /* Decode the I instruction format */ + + static String decode_Iform(int addr, int inst, int opcode) + { + int target; + int AA, LK; + String mnemonic; + + AA = bits(inst,30,30); + LK = bits(inst,31,31); + target = (((inst) & ~3) << 6) >> 6; + if (AA!=0) { + mnemonic = (LK!=0) ? "bla" : "ba"; + } else { + target += addr; + mnemonic = (LK!=0) ? "bl" : "b"; + } + destination = target; + return " ".substring(mnemonic.length()) + mnemonic + " " + Integer.toHexString(destination); + } + + /* Decode the SC instruction format */ + + static String decode_SCform(int inst, int opcode) + { + int SA, LK, LEV, FL1, FL2, SV; + + SA = bits(inst,30,30); + LK = bits(inst,31,31); + if (SA != 0) + { + SV = bits(inst,16,29); + String mnemonic = (LK!=0) ? "svcla" : "svca"; + return " ".substring(mnemonic.length()) + mnemonic + + " "+intAsHexString(SV); + } + else + { + LEV = bits(inst,20,26); + FL1 = bits(inst,16,19); + FL2 = bits(inst,27,29); + String mnemonic = (LK!=0) ? "svcl" : "svc"; + return " ".substring(mnemonic.length()) + mnemonic + + " "+intAsHexString(LEV)+","+intAsHexString(FL1)+","+ + intAsHexString(FL2); + } + } + + /* Decode the XL instruction format */ + + static String decode_XLform(int inst, int opcode) + { + String mnemonic; + int ext_opcode; + int LK, BO, BI, BB; + int BF, BFA, BT, BA; + opcode_tab opcode_info; + int cr_field; + String branch_name; + + ext_opcode = bits(inst,21,30); + opcode_info = XLform[ext_opcode >> 4]; /* shift to get XL table index */ + mnemonic = opcode_info.mnemonic; + switch(opcode_info.format) + { + case 0: + return " ".substring(mnemonic.length()) + mnemonic; + case 1: + BO = bits(inst,6,10); + BI = bits(inst,11,15); + LK = bits(inst,31,31); + cr_field = (byte) (BI>>2); + branch_name = build_branch_op(BO,1 << (3 - (BI&3)),LK,0,ext_opcode); + if (cr_field!=0) {/* Not CR 0 ? */ + return " ".substring(branch_name.length()) + branch_name + + " "+cr_field; + } else { + return " ".substring(branch_name.length()) + branch_name; + } + case 2: + BF = bits(inst,6,10); + BFA = bits(inst,11,13); + return " ".substring(mnemonic.length()) + mnemonic + + " cr"+BF+","+intAsHexString(BFA); + case 3: + BT = bits(inst,6,10); + BA = bits(inst,11,15); + BB = bits(inst,16,20); + return " ".substring(mnemonic.length()) + mnemonic + + " "+intAsHexString(BT)+","+intAsHexString(BA)+","+ + intAsHexString(BB); + default: + return " Invalid opcode"; + } + } + + static String[] Mforms = { "rlimi", "rlimi.", "rlinm", "rlinm.", + "rlmi", "rlmi.", "rlnm", "rlnm."}; + + /* Decode the M instruction format */ + + static String decode_Mform(int inst, int opcode) + { + int RS, RA; + int MB, ME, Rc; + int SH_RB; + String asm_mnemonic; + + RS = bits(inst,6,10); + RA = bits(inst,11,15); + SH_RB = bits(inst,16,20); + MB = bits(inst,21,25); + ME = bits(inst,26,30); + Rc = inst & 1; + + asm_mnemonic = Mforms[(opcode - 20) * 2 + Rc]; + if ((opcode < 20) || ((opcode >>> 23)!=0)) { + return " Invalid opcode"; + } else { + if (opcode == 21) { /* sri and sli are special forms of rlmni */ + if ((ME == 32) && (MB == (31-SH_RB))) { + String mnemonic = (Rc!=0) ? "sri." : "sri"; + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(RS)+","+intAsHexString(MB); + } else if ((MB == 0) && (SH_RB == (31-ME))) { + String mnemonic = (Rc!=0) ? "sli." : "sli"; + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(RS)+","+intAsHexString(SH_RB); + } else { + return " ".substring(asm_mnemonic.length()) + asm_mnemonic + + " "+rname(RA)+","+rname(RS)+","+intAsHexString(SH_RB)+","+ + intAsHexString(MB)+","+intAsHexString(ME) ; + } + } else { + return " ".substring(asm_mnemonic.length()) + asm_mnemonic + + " "+rname(RA)+","+rname(RS)+","+intAsHexString(SH_RB)+","+ + intAsHexString(MB)+","+intAsHexString(ME) ; + } + } + } + + static opcodeXX searchXX(int key, opcodeXX[] where) { + + for (opcodeXX opxx : where) { + if (opxx.key == key) return opxx; + } + + return null; + + } + + /* Decode opcode 30 and then the relevent format */ + + static String decode_opcode30(int inst) + { + opcodeXX search_results; + String mnemonic; + + int testkey = bits(inst,27,30); + search_results = searchXX(testkey, opcode30); + + if (search_results == null) { + return " Invalid opcode"; + } + + mnemonic = search_results.mnemonic; + + switch(search_results.form) + { + case MDS_FORM: + return decode_MDSform(inst, mnemonic); + case MD_FORM: + return decode_MDform(inst, mnemonic); + default: + return " Invalid opcode"; + } + } + + /* Decode the MD instruction format */ + static String decode_MDform(int inst, String mnemonic) + { + int RS, RA, SH, MB; + + RS = bits(inst,6,10); + RA = bits(inst,11,15); + SH = ((inst&0x2) >> 4) | bits(inst,16,20); + MB = (inst&0x20) | bits(inst,21,25); + return " ".substring(mnemonic.length()) + mnemonic + + rname(RA) + ", " + rname(RS) + ", " + SH + ", " + MB; + } + + /* Decode the MDS instruction format */ + static String decode_MDSform(int inst, String mnemonic) + { + int RS, RA, RB, MB; + + RS = bits(inst,6,10); + RA = bits(inst,11,15); + RB = bits(inst,16,20); + MB = (inst&0x20) | bits(inst,21,25); + return " ".substring(mnemonic.length()) + mnemonic + + rname(RA) + ", " + rname(RS) + ", " + rname(RB) + ", " + MB; + } + + /* Decode the A instruction format */ + /* Decode opcode 31 and then the relevent format */ + + static String decode_opcode31(int inst) + { + opcodeXX search_results; + int format; + String mnemonic; + + + int testkey = bits(inst,21,31); + search_results = searchXX(testkey, opcode31); + + if (search_results == null) { + return " Invalid opcode"; + } + + mnemonic = search_results.mnemonic; + format = search_results.format; + switch(search_results.form) + { + case X_FORM: + return decode_Xform(inst,mnemonic,format,testkey); + case XFX_FORM: + return decode_XFXform(inst); + case XO_FORM: + return decode_XOform(inst,mnemonic,format); + case XS_FORM: + return decode_XSform(inst,mnemonic,format); + default: + return " Invalid opcode"; + } + } + + /* Decode the X instruction format */ + + static String decode_Xform(int inst, String mnemonic, int format, int ext_op) + { + int rt,RA,RB,NB,SH,FRS,SPR,FRT; + int BF,BFA,I,BT,SR,FRA,FRB,TO; + String asm_mnemonic, common_opt; + + FRS = FRT = TO = BT = rt = bits(inst,6,10); + FRB = NB = SH = RB = I = bits(inst,16,20); + FRA = SPR = SR = RA = bits(inst,11,15); + BFA = bits(inst,11,13); + I = bits(inst,16,19); + BF = bits(inst,6,8); + + switch(format) + { + case 0: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(rt); + case 1: + return " ".substring(mnemonic.length()) + mnemonic; + case 2: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt); + case 3: + common_opt = SPR_name(SPR); + if (common_opt != null) { + asm_mnemonic = mnemonic.substring(0, 2) + common_opt; + return " ".substring(asm_mnemonic.length()) + asm_mnemonic + + " "+rname(rt); + } else {/* reserved register? */ + return " ".substring(mnemonic.length()) + mnemonic + + " "+intAsHexString(SPR)+","+rname(rt); + } + case 4: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RB); + case 5: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RA); + case 6: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(RB); + case 7: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RA)+","+rname(RB); + case 8: + if ((ext_op == 888) || (ext_op == 889)) { + if (rt == RB) { + String mne = (ext_op == 889) ? "mr." : "mr"; + return " ".substring(mne.length()) + mne + + " "+rname(RA)+","+rname(rt); + } + } + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(rt)+","+rname(RB); + case 9: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(rt); + case 10: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(rt)+","+rname(RA)+","+intAsHexString(NB); + case 11: + return " ".substring(mnemonic.length()) + mnemonic + + " "+rname(RA)+","+rname(rt)+","+intAsHexString(SH); + case 12: + return " ".substring(mnemonic.length()) + mnemonic + + " fr"+FRS+","+rname(RA)+","+rname(RB); + case 13: + return " ".substring(mnemonic.length()) + mnemonic + + " fr"+FRT; + case 14: + return " ".substring(mnemonic.length()) + mnemonic + + " cr"+BF+","+intAsHexString(BFA); + case 15: + return " ".substring(mnemonic.length()) + mnemonic + + " cr"+BF+","+intAsHexString(I); + c... [truncated message content] |
From: <cap...@us...> - 2007-03-18 22:49:42
|
Revision: 4 http://svn.sourceforge.net/pearcolator/?rev=4&view=rev Author: captain5050 Date: 2007-03-18 15:49:42 -0700 (Sun, 18 Mar 2007) Log Message: ----------- More build fixes Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_Registers.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-03-18 22:49:42 UTC (rev 4) @@ -363,7 +363,7 @@ } OPT_RegisterOperand lt = new OPT_RegisterOperand(crFieldMap_Lt[crf], VM_TypeReference.Boolean); OPT_RegisterOperand gt = new OPT_RegisterOperand(crFieldMap_Gt[crf], VM_TypeReference.Boolean); - OPT_RegisterOperand lt = new OPT_RegisterOperand(crFieldMap_Eq[crf], VM_TypeReference.Boolean); + OPT_RegisterOperand eq = new OPT_RegisterOperand(crFieldMap_Eq[crf], VM_TypeReference.Boolean); OPT_RegisterOperand so = new OPT_RegisterOperand(crFieldMap_SO[crf], VM_TypeReference.Boolean); OPT_RegisterOperand arrayref = gc.temps.makeTemp(VM_TypeReference.BooleanArray); @@ -384,9 +384,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -397,9 +397,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -410,9 +410,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -434,7 +434,7 @@ { OPT_RegisterOperand lt = new OPT_RegisterOperand(crFieldMap_Lt[crf], VM_TypeReference.Boolean); OPT_RegisterOperand gt = new OPT_RegisterOperand(crFieldMap_Gt[crf], VM_TypeReference.Boolean); - OPT_RegisterOperand lt = new OPT_RegisterOperand(crFieldMap_Eq[crf], VM_TypeReference.Boolean); + OPT_RegisterOperand eq = new OPT_RegisterOperand(crFieldMap_Eq[crf], VM_TypeReference.Boolean); OPT_RegisterOperand so = new OPT_RegisterOperand(crFieldMap_SO[crf], VM_TypeReference.Boolean); OPT_RegisterOperand arrayref = gc.temps.makeTemp(VM_TypeReference.BooleanArray); @@ -455,9 +455,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_gt"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -468,9 +468,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_eq"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -481,9 +481,9 @@ arrayref, new OPT_IntConstantOperand(crf), new OPT_LocationOperand(VM_TypeReference.BooleanArray), new OPT_TrueGuardOperand())); - VM_FieldReference ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), - VM_Atom.findOrCreateAsciiAtom("[Z") - ).asFieldReference(); + ref = VM_MemberReference.findOrCreate(psTref,VM_Atom.findOrCreateAsciiAtom("crf_so"), + VM_Atom.findOrCreateAsciiAtom("[Z") + ).asFieldReference(); appendInstructionToCurrentBlock(GetField.create(GETFIELD, arrayref, gc.makeLocal(1,psTref), new OPT_AddressConstantOperand(ref.peekResolvedField().getOffset()), @@ -915,13 +915,13 @@ int crf = crb >> 2; switch(crb & 0x3) { case 0: - return ppc2ir.getCR_Lt_Register(crf); + return getCR_Lt_Register(crf); case 1: - return ppc2ir.getCR_Gt_Register(crf); + return getCR_Gt_Register(crf); case 2: - return ppc2ir.getCR_Eq_Register(crf); + return getCR_Eq_Register(crf); case 3: - return ppc2ir.getCR_SO_Register(crf); + return getCR_SO_Register(crf); default: DBT_OptimizingCompilerException.UNREACHABLE(); } Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-03-18 22:49:42 UTC (rev 4) @@ -589,7 +589,7 @@ OPT_BranchProfileOperand likelyOp = ppc2ir.getConditionalBranchProfileOperand(likely); // Grab the flag to compare - OPT_RegisterOperand flag = getCRB_Register(BI); + OPT_RegisterOperand flag = ppc2ir.getCRB_Register(BI); // The condition to test OPT_ConditionOperand condOp; Modified: src/org/binarytranslator/arch/x86/decoder/X86_Registers.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_Registers.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/arch/x86/decoder/X86_Registers.java 2007-03-18 22:49:42 UTC (rev 4) @@ -8,9 +8,7 @@ */ package org.binarytranslator.arch.x86; -import org.binarytranslator.generic.memory.Registers; - -public class X86_Registers extends Registers { +public class X86_Registers { String[] name32 = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; private int[] GP32 = new int[8]; Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-03-18 22:49:42 UTC (rev 4) @@ -1282,71 +1282,4 @@ public OPT_RegisterOperand makeTemp(VM_TypeReference type) { return gc.temps.makeTemp(type); } - - /** - * Remove conditional moves - */ - static void eliminateConditionalMoves(OPT_IR ir) { - OPT_BasicBlock curBB = ir.gc.prologue; - while(curBB != null) { - OPT_Instruction curInstr = curBB.firstInstruction(); - loop_over_instructions: - while(BBend.conforms(curInstr) == false) { - if(CondMove.conforms(curInstr) && (curInstr.operator() == INT_COND_MOVE)) { - OPT_BasicBlock compareBlock; // block containing compare instruction - OPT_BasicBlock trueBlock; // block containing true payload - OPT_BasicBlock falseBlock; // block containing false payload - OPT_BasicBlock restOfBlock; // the rest of the block - - // Set up blocks - compareBlock = curBB; - trueBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); - falseBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); - restOfBlock = compareBlock.splitNodeAt(curInstr, ir); - ir.gc.cfg.linkInCodeOrder(compareBlock, falseBlock); - ir.gc.cfg.linkInCodeOrder(falseBlock, trueBlock); - ir.gc.cfg.linkInCodeOrder(trueBlock, restOfBlock); - - // Set up values - OPT_RegisterOperand result = CondMove.getResult(curInstr); - OPT_Operand val1 = CondMove.getVal1(curInstr); - OPT_Operand val2 = CondMove.getVal2(curInstr); - OPT_ConditionOperand cond = CondMove.getCond(curInstr); - OPT_Operand trueValue = CondMove.getTrueValue(curInstr); - OPT_Operand falseValue = CondMove.getFalseValue(curInstr); - - // Create comparison - OPT_Operator cmpType; - if(val1.isInt()){ - cmpType = INT_IFCMP; - } - else if (val1.isDouble()){ - cmpType = DOUBLE_IFCMP; - } - else { - throw new Error("Unexpected type of val1: " + val1); - } - IfCmp.mutate(curInstr, cmpType, null, val1, val2, cond, trueBlock.makeJumpTarget(), OPT_BranchProfileOperand.likely()); - compareBlock.deleteNormalOut(); - compareBlock.insertOut(trueBlock); - compareBlock.insertOut(falseBlock); - - // Create false code - falseBlock.appendInstruction(Move.create(INT_MOVE, result, falseValue)); - falseBlock.appendInstruction(Goto.create(GOTO,restOfBlock.makeJumpTarget())); - falseBlock.insertOut(restOfBlock); - - // Create true code - trueBlock.appendInstruction(Move.create(INT_MOVE, result, trueValue)); - trueBlock.insertOut(restOfBlock); - - // Move along - curBB = restOfBlock; - curInstr = curBB.firstInstruction(); - } - curInstr = curInstr.nextInstructionInCodeOrder(); - } - curBB = curBB.nextBasicBlockInCodeOrder(); - } - } } Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-03-18 22:49:42 UTC (rev 4) @@ -284,7 +284,7 @@ * system) */ public synchronized void replaceCompiledTrace(VM_CompiledMethod cm, DBT_Trace trace) { - VM_CodeArray code = cm.getInstructions(); + VM_CodeArray code = cm.getEntryCodeArray(); codeHash.put(new Integer(trace.pc), code); } @@ -304,7 +304,7 @@ trace.compile(); VM_CompiledMethod cm = trace.getCurrentCompiledMethod(); replaceCompiledTrace(cm, trace); - return cm.getInstructions(); + return cm.getEntryCodeArray(); } /** Modified: src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2007-03-18 22:49:42 UTC (rev 4) @@ -9,11 +9,27 @@ package org.binarytranslator.vmInterface; import org.binarytranslator.generic.decoder.DecoderUtils; import org.jikesrvm.opt.OPT_CompilerPhase; -import org.jikesrvm.opt.ir.OPT_IR; +import org.jikesrvm.VM_Configuration; + +import org.jikesrvm.opt.ir.OPT_BasicBlock; import org.jikesrvm.opt.ir.OPT_GenerationContext; import org.jikesrvm.opt.ir.OPT_HIRInfo; -import org.jikesrvm.VM_Configuration; +import org.jikesrvm.opt.ir.OPT_IR; +import org.jikesrvm.opt.ir.OPT_Instruction; +import static org.jikesrvm.opt.ir.OPT_Operators.*; +import org.jikesrvm.opt.ir.OPT_Operator; +import org.jikesrvm.opt.ir.BBend; +import org.jikesrvm.opt.ir.CondMove; +import org.jikesrvm.opt.ir.Goto; +import org.jikesrvm.opt.ir.IfCmp; +import org.jikesrvm.opt.ir.Move; + +import org.jikesrvm.opt.ir.OPT_Operand; +import org.jikesrvm.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.opt.ir.OPT_RegisterOperand; + /** * The OPT_CompilerPhase which translates from PowerPC machine code * into HIR. It is used in PPC_OptimizationPlanner (in place of @@ -61,10 +77,76 @@ } if (VM_Configuration.BuildForPowerPC) { - DecoderUtils.eliminateConditionalMoves(ir); + eliminateConditionalMoves(ir); } } protected abstract void generateHIR(OPT_GenerationContext gc); - protected abstract void eliminateConditionalMoves(OPT_IR ir); + + /** + * Remove conditional moves + */ + public static void eliminateConditionalMoves(OPT_IR ir) { + OPT_BasicBlock curBB = ir.gc.prologue; + while(curBB != null) { + OPT_Instruction curInstr = curBB.firstInstruction(); + loop_over_instructions: + while(BBend.conforms(curInstr) == false) { + if(CondMove.conforms(curInstr) && (curInstr.operator() == INT_COND_MOVE)) { + OPT_BasicBlock compareBlock; // block containing compare instruction + OPT_BasicBlock trueBlock; // block containing true payload + OPT_BasicBlock falseBlock; // block containing false payload + OPT_BasicBlock restOfBlock; // the rest of the block + + // Set up blocks + compareBlock = curBB; + trueBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); + falseBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); + restOfBlock = compareBlock.splitNodeAt(curInstr, ir); + ir.gc.cfg.linkInCodeOrder(compareBlock, falseBlock); + ir.gc.cfg.linkInCodeOrder(falseBlock, trueBlock); + ir.gc.cfg.linkInCodeOrder(trueBlock, restOfBlock); + + // Set up values + OPT_RegisterOperand result = CondMove.getResult(curInstr); + OPT_Operand val1 = CondMove.getVal1(curInstr); + OPT_Operand val2 = CondMove.getVal2(curInstr); + OPT_ConditionOperand cond = CondMove.getCond(curInstr); + OPT_Operand trueValue = CondMove.getTrueValue(curInstr); + OPT_Operand falseValue = CondMove.getFalseValue(curInstr); + + // Create comparison + OPT_Operator cmpType; + if(val1.isInt()){ + cmpType = INT_IFCMP; + } + else if (val1.isDouble()){ + cmpType = DOUBLE_IFCMP; + } + else { + throw new Error("Unexpected type of val1: " + val1); + } + IfCmp.mutate(curInstr, cmpType, null, val1, val2, cond, trueBlock.makeJumpTarget(), OPT_BranchProfileOperand.likely()); + compareBlock.deleteNormalOut(); + compareBlock.insertOut(trueBlock); + compareBlock.insertOut(falseBlock); + + // Create false code + falseBlock.appendInstruction(Move.create(INT_MOVE, result, falseValue)); + falseBlock.appendInstruction(Goto.create(GOTO,restOfBlock.makeJumpTarget())); + falseBlock.insertOut(restOfBlock); + + // Create true code + trueBlock.appendInstruction(Move.create(INT_MOVE, result, trueValue)); + trueBlock.insertOut(restOfBlock); + + // Move along + curBB = restOfBlock; + curInstr = curBB.firstInstruction(); + } + curInstr = curInstr.nextInstructionInCodeOrder(); + } + curBB = curBB.nextBasicBlockInCodeOrder(); + } + } } Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-03-16 23:59:58 UTC (rev 3) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-03-18 22:49:42 UTC (rev 4) @@ -67,7 +67,7 @@ */ private static VM_Class dummyRunner; private static VM_NormalMethod invokeCode; - private static int invokeCode_modifiers; + private static short invokeCode_modifiers; private static VM_TypeReference dummyRunnerTypeRef; private static VM_MemberReference dummyRunnerMemRef; private static VM_Atom invokeCodeDescriptor; @@ -125,14 +125,14 @@ invokeCode.getOperandWords(), invokeCode.bytecodes, invokeCode.getExceptionHandlerMap(), - new int[0], null, null, null, null, null, null, null); + new int[0], null, null, null, null, null); - this.offset = VM_Statics.allocateSlot(VM_Statics.METHOD) << LOG_BYTES_IN_INT; + this.offset = invokeCode.getOffset().toInt(); - this.summary |= HAS_ALLOCATION | HAS_THROW | HAS_INVOKE | - HAS_FIELD_READ | HAS_FIELD_WRITE | HAS_ARRAY_READ | HAS_ARRAY_WRITE | - HAS_COND_BRANCH | HAS_SWITCH | HAS_BACK_BRANCH | - 256; + this.summaryFlags |= HAS_ALLOCATION | HAS_THROW | HAS_INVOKE | + HAS_FIELD_READ | HAS_FIELD_WRITE | HAS_ARRAY_READ | HAS_ARRAY_WRITE | + HAS_COND_BRANCH | HAS_SWITCH | HAS_BACK_BRANCH; + this.summarySize = 256; this.ps = ps; pc = startPC; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-02 12:11:29
|
Revision: 19 http://svn.sourceforge.net/pearcolator/?rev=19&view=rev Author: michael_baer Date: 2007-04-02 05:11:23 -0700 (Mon, 02 Apr 2007) Log Message: ----------- Added support for building with the latest JRVM. Modified Paths: -------------- ext/DBT_Dummy.java ext/org/jikesrvm/classloader/VM_Method.java ext/org/jikesrvm/classloader/VM_NormalMethod.java ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java ext/org/jikesrvm/compilers/opt/ir/OPT_ConditionOperand.java ext/org/jikesrvm/compilers/opt/ir/OPT_ConvertBCtoHIR.java ext/org/jikesrvm/compilers/opt/ir/OPT_GenerationContext.java ext/org/jikesrvm/compilers/opt/ir/OPT_HIRGenerator.java ext/org/jikesrvm/compilers/opt/ir/OPT_HIRInfo.java ext/org/jikesrvm/compilers/opt/ir/ia32/OPT_IA32ConditionOperand.java rvmroot.patch src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/abi/linux/PPC_LinuxSystemCalls.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/branch/ProcedureInformation.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/fault/BadInstructionException.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/loader/Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java src/org/binarytranslator/vmInterface/DBT_OptimizingCompilerException.java src/org/binarytranslator/vmInterface/DBT_Trace.java src/org/binarytranslator/vmInterface/TranslationHelper.java Added Paths: ----------- ext/org/jikesrvm/compilers/ ext/org/jikesrvm/compilers/common/ ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java ext/org/jikesrvm/compilers/opt/ Removed Paths: ------------- ext/org/jikesrvm/opt/ Modified: ext/DBT_Dummy.java =================================================================== --- ext/DBT_Dummy.java 2007-04-01 12:27:50 UTC (rev 18) +++ ext/DBT_Dummy.java 2007-04-02 12:11:23 UTC (rev 19) @@ -1,3 +1,4 @@ + /* * This file is part of binarytranslator.org. The binarytranslator.org * project is distributed under the Common Public License (CPL). @@ -12,16 +13,16 @@ * to find every class comprising the chnages to the opt compiler for DBT */ class OptDummy { - static org.jikesrvm.opt.ir.ia32.OPT_IA32ConditionOperand a; - static org.jikesrvm.opt.ir.OPT_HIRGenerator b; - static org.jikesrvm.opt.ir.OPT_GenerationContext c; - static org.jikesrvm.opt.ir.OPT_ConditionOperand d; - static org.jikesrvm.opt.ir.OPT_HIRInfo e; - static org.jikesrvm.opt.OPT_Simplifier f; + static org.jikesrvm.compilers.opt.ir.ia32.OPT_IA32ConditionOperand a; + static org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator b; + static org.jikesrvm.compilers.opt.ir.OPT_GenerationContext c; + static org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand d; + static org.jikesrvm.compilers.opt.ir.OPT_HIRInfo e; + static org.jikesrvm.compilers.opt.OPT_Simplifier f; static org.jikesrvm.ppc.PPC_Disassembler g; static org.jikesrvm.classloader.VM_Method j; static org.jikesrvm.classloader.VM_Member k; static org.jikesrvm.classloader.VM_NormalMethod l; - static org.jikesrvm.VM_RuntimeCompiler m; - static org.jikesrvm.opt.ir.OPT_ConvertBCtoHIR n; + static org.jikesrvm.compilers.common.VM_RuntimeCompiler m; + static org.jikesrvm.compilers.opt.ir.OPT_ConvertBCtoHIR n; } Modified: ext/org/jikesrvm/classloader/VM_Method.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Method.java 2007-04-01 12:27:50 UTC (rev 18) +++ ext/org/jikesrvm/classloader/VM_Method.java 2007-04-02 12:11:23 UTC (rev 19) @@ -11,6 +11,8 @@ import org.jikesrvm.*; import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; import org.jikesrvm.ArchitectureSpecific.VM_LazyCompilationTrampolineGenerator; +import org.jikesrvm.compilers.common.VM_CompiledMethod; +import org.jikesrvm.compilers.common.VM_CompiledMethods; import org.jikesrvm.runtime.VM_Statics; import org.jikesrvm.runtime.VM_Entrypoints; Modified: ext/org/jikesrvm/classloader/VM_NormalMethod.java =================================================================== --- ext/org/jikesrvm/classloader/VM_NormalMethod.java 2007-04-01 12:27:50 UTC (rev 18) +++ ext/org/jikesrvm/classloader/VM_NormalMethod.java 2007-04-02 12:11:23 UTC (rev 19) @@ -10,9 +10,12 @@ import org.jikesrvm.*; import org.vmmagic.pragma.*; -import org.jikesrvm.opt.ir.OPT_HIRGenerator; -import org.jikesrvm.opt.ir.OPT_BC2IR; -import org.jikesrvm.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.common.VM_BootImageCompiler; +import org.jikesrvm.compilers.common.VM_CompiledMethod; +import org.jikesrvm.compilers.common.VM_RuntimeCompiler; +import org.jikesrvm.compilers.opt.ir.OPT_BC2IR; +import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.jikesrvm.runtime.VM_DynamicLink; /** Added: ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java =================================================================== --- ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java (rev 0) +++ ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java 2007-04-02 12:11:23 UTC (rev 19) @@ -0,0 +1,855 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp. 2001, 2005 + */ +package org.jikesrvm.compilers.common; + +import org.jikesrvm.*; +import org.jikesrvm.classloader.*; +import org.jikesrvm.compilers.baseline.*; +import org.jikesrvm.compilers.opt.*; +import org.jikesrvm.adaptive.controller.VM_Controller; +import org.jikesrvm.adaptive.controller.VM_ControllerMemory; +import org.jikesrvm.adaptive.controller.VM_ControllerPlan; +import org.jikesrvm.adaptive.recompilation.VM_InvocationCounts; +import org.jikesrvm.adaptive.recompilation.VM_PreCompile; +import org.jikesrvm.adaptive.recompilation.instrumentation.VM_AOSInstrumentationPlan; +import org.jikesrvm.adaptive.util.*; +import org.jikesrvm.ArchitectureSpecific.VM_JNICompiler; +import org.jikesrvm.runtime.VM_Time; +import org.jikesrvm.scheduler.VM_Thread; + +/** + * Harness to select which compiler to dynamically compile a method in first + * invocation. + * + * A place to put code common to all runtime compilers. This includes + * instrumentation code to get equivalent data for each of the runtime + * compilers. + * <p> + * We collect the following data for each compiler + * <ol> + * <li> total number of methods complied by the compiler + * <li> total compilation time in milliseconds. + * <li> total number of bytes of bytecodes compiled by the compiler (under the + * assumption that there is no padding in the bytecode array and thus + * VM_Method.getBytecodes().length is the number bytes of bytecode for a method) + * <li> total number of machine code insructions generated by the compiler + * (under the assumption that there is no (excessive) padding in the machine + * code array and thus VM_CompiledMethod.numberOfInsturctions() is a close + * enough approximation of the number of machinecodes generated) + * </ol> + * Note that even if 3. & 4. are inflated due to padding, the numbers will still + * be an accurate measure of the space costs of the compile-only approach. + * + * @author Matthew Arnold + * @author Dave Grove + * @author Michael Hind + */ +public class VM_RuntimeCompiler implements VM_Constants, + VM_Callbacks.ExitMonitor { + + // Use these to encode the compiler for record() + public static final byte JNI_COMPILER = 0; + + public static final byte BASELINE_COMPILER = 1; + + public static final byte OPT_COMPILER = 2; + + // Data accumulators + private static final String[] name = { "JNI\t", "Base\t", "Opt\t" }; // Output + // names + + private static int[] totalMethods = { 0, 0, 0 }; + + private static double[] totalCompTime = { 0, 0, 0 }; + + private static int[] totalBCLength = { 0, 0, 0 }; + + private static int[] totalMCLength = { 0, 0, 0 }; + + // running sum of the natural logs of the rates, + // used for geometric mean, the product of rates is too big for doubles + // so we use the principle of logs to help us + // We compute e ** ((log a + log b + ... + log n) / n ) + private static double[] totalLogOfRates = { 0, 0, 0 }; + + // We can't record values until Math.log is loaded, so we miss the first few + private static int[] totalLogValueMethods = { 0, 0, 0 }; + + private static String[] earlyOptArgs = new String[0]; + + // is the opt compiler usable? + protected static boolean compilerEnabled; + + // is opt compiler currently in use? + // This flag is used to detect/avoid recursive opt compilation. + // (ie when opt compilation causes a method to be compiled). + // We also make all public entrypoints static synchronized methods + // because the opt compiler is not reentrant. + // When we actually fix defect 2912, we'll have to implement a different + // scheme that can distinguish between recursive opt compilation by the same + // thread (always bad) and parallel opt compilation (currently bad, future + // ok). + // NOTE: This code can be quite subtle, so please be absolutely sure + // you know what you're doing before modifying it!!! + protected static boolean compilationInProgress; + + // One time check to optionally preload and compile a specified class + protected static boolean preloadChecked = false; + + // Cache objects needed to cons up compilation plans + // TODO: cutting link to opt compiler by declaring type as object. + public static Object /* OPT_Options */options; + + public static Object /* OPT_OptimizationPlanElement[] */optimizationPlan; + + /** + * To be called when the VM is about to exit. + * + * @param value + * the exit value + */ + public void notifyExit(int value) { + report(false); + } + + /** + * This method records the time and sizes (bytecode and machine code) for a + * compilation. + * + * @param compiler + * the compiler used + * @param method + * the resulting VM_Method + * @param compiledMethod + * the resulting compiled method + */ + public static void record(byte compiler, VM_NormalMethod method, + VM_CompiledMethod compiledMethod) { + + recordCompilation(compiler, method.getBytecodeLength(), compiledMethod + .numberOfInstructions(), compiledMethod.getCompilationTime()); + + if (VM.BuildForAdaptiveSystem) { + if (VM_AOSLogging.booted()) { + VM_AOSLogging.recordUpdatedCompilationRates(compiler, method, method + .getBytecodeLength(), totalBCLength[compiler], compiledMethod + .numberOfInstructions(), totalMCLength[compiler], compiledMethod + .getCompilationTime(), totalCompTime[compiler], + totalLogOfRates[compiler], totalLogValueMethods[compiler], + totalMethods[compiler]); + } + } + } + + /** + * This method records the time and sizes (bytecode and machine code) for a + * compilation + * + * @param compiler + * the compiler used + * @param method + * the resulting VM_Method + * @param compiledMethod + * the resulting compiled method + */ + public static void record(byte compiler, VM_NativeMethod method, + VM_CompiledMethod compiledMethod) { + + recordCompilation(compiler, 0, // don't have any bytecode info, its native + compiledMethod.numberOfInstructions(), compiledMethod + .getCompilationTime()); + } + + /** + * This method does the actual recording + * + * @param compiler + * the compiler used + * @param BCLength + * the number of bytecodes in method source + * @param MCLength + * the length of the generated machine code + * @param compTime + * the compilation time in ms + */ + private static void recordCompilation(byte compiler, int BCLength, + int MCLength, double compTime) { + + totalMethods[compiler]++; + totalMCLength[compiler] += MCLength; + totalCompTime[compiler] += compTime; + + // Comp rate not useful for JNI compiler because there is no bytecode! + if (compiler != JNI_COMPILER) { + totalBCLength[compiler] += BCLength; + double rate = BCLength / compTime; + + // need to be fully booted before calling log + if (VM.fullyBooted) { + // we want the geometric mean, but the product of rates is too big + // for doubles, so we use the principle of logs to help us + // We compute e ** ((log a + log b + ... + log n) / n ) + totalLogOfRates[compiler] += Math.log(rate); + totalLogValueMethods[compiler]++; + } + } + } + + /** + * This method produces a summary report of compilation activities + * + * @param explain + * Explains the metrics used in the report + */ + public static void report(boolean explain) { + VM.sysWrite("\n\t\tCompilation Subsystem Report\n"); + VM.sysWrite("Comp\t#Meths\tTime\tbcb/ms\tmcb/bcb\tMCKB\tBCKB\n"); + for (int i = 0; i <= name.length - 1; i++) { + if (totalMethods[i] > 0) { + VM.sysWrite(name[i]); + // Number of methods + VM.sysWrite(totalMethods[i]); + VM.sysWrite("\t"); + // Compilation time + VM.sysWrite(totalCompTime[i]); + VM.sysWrite("\t"); + + if (i == JNI_COMPILER) { + VM.sysWrite("NA"); + } else { + // Bytecode bytes per millisecond, + // use unweighted geomean + VM + .sysWrite(Math.exp(totalLogOfRates[i] / totalLogValueMethods[i]), + 2); + } + VM.sysWrite("\t"); + // Ratio of machine code bytes to bytecode bytes + if (i != JNI_COMPILER) { + VM + .sysWrite( + (double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH) + / (double) totalBCLength[i], 2); + } else { + VM.sysWrite("NA"); + } + VM.sysWrite("\t"); + // Generated machine code Kbytes + VM + .sysWrite( + (double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH) / 1024, + 1); + VM.sysWrite("\t"); + // Compiled bytecode Kbytes + if (i != JNI_COMPILER) { + VM.sysWrite((double) totalBCLength[i] / 1024, 1); + } else { + VM.sysWrite("NA"); + } + VM.sysWrite("\n"); + } + } + if (explain) { + // Generate an explanation of the metrics reported + VM.sysWrite("\t\t\tExplanation of Metrics\n"); + VM + .sysWrite("#Meths:\t\tTotal number of methods compiled by the compiler\n"); + VM.sysWrite("Time:\t\tTotal compilation time in milliseconds\n"); + VM + .sysWrite("bcb/ms:\t\tNumber of bytecode bytes complied per millisecond\n"); + VM.sysWrite("mcb/bcb:\tRatio of machine code bytes to bytecode bytes\n"); + VM + .sysWrite("MCKB:\t\tTotal number of machine code bytes generated in kilobytes\n"); + VM + .sysWrite("BCKB:\t\tTotal number of bytecode bytes compiled in kilobytes\n"); + } + + VM_BaselineCompiler.generateBaselineCompilerSubsystemReport(explain); + + if (VM.BuildForAdaptiveSystem) { + // Get the opt's report + VM_TypeReference theTypeRef = VM_TypeReference + .findOrCreate( + VM_BootstrapClassLoader.getBootstrapClassLoader(), + VM_Atom + .findOrCreateAsciiAtom("Lorg/jikesrvm/opt/OPT_OptimizationPlanner;")); + VM_Type theType = theTypeRef.peekResolvedType(); + if (theType != null && theType.asClass().isInitialized()) { + OPT_OptimizationPlanner + .generateOptimizingCompilerSubsystemReport(explain); + } else { + VM + .sysWrite("\n\tNot generating Optimizing Compiler SubSystem Report because \n"); + VM.sysWrite("\tthe opt compiler was never invoked.\n\n"); + } + } + } + + /** + * Return the current estimate of basline-compiler rate, in bcb/msec + */ + public static double getBaselineRate() { + return Math.exp(totalLogOfRates[BASELINE_COMPILER] + / totalLogValueMethods[BASELINE_COMPILER]); + } + + /** + * This method will compile the passed method using the baseline compiler. + * + * @param method + * the method to compile + */ + public static VM_CompiledMethod baselineCompile(VM_NormalMethod method) { + VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.BASELINE); + long start = 0; + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + start = VM_Thread.getCurrentThread().accumulateCycles(); + } + + VM_CompiledMethod cm = VM_BaselineCompiler.compile(method); + + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + long end = VM_Thread.getCurrentThread().accumulateCycles(); + double compileTime = VM_Time.cyclesToMillis(end - start); + cm.setCompilationTime(compileTime); + record(BASELINE_COMPILER, method, cm); + } + + return cm; + } + + /** + * Process command line argument destined for the opt compiler + */ + public static void processOptCommandLineArg(String prefix, String arg) { + if (VM.BuildForAdaptiveSystem) { + if (compilerEnabled) { + if (((OPT_Options) options).processAsOption(prefix, arg)) { + // update the optimization plan to reflect the new command line + // argument + optimizationPlan = OPT_OptimizationPlanner + .createOptimizationPlan((OPT_Options) options); + } else { + VM.sysWrite("Unrecognized opt compiler argument \"" + arg + "\""); + VM.sysExit(VM.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG); + } + } else { + String[] tmp = new String[earlyOptArgs.length + 2]; + for (int i = 0; i < earlyOptArgs.length; i++) { + tmp[i] = earlyOptArgs[i]; + } + earlyOptArgs = tmp; + earlyOptArgs[earlyOptArgs.length - 2] = prefix; + earlyOptArgs[earlyOptArgs.length - 1] = arg; + } + } else { + if (VM.VerifyAssertions) + VM._assert(NOT_REACHED); + } + } + + /** + * attempt to compile the passed method with the OPT_Compiler. Don't handle + * OPT_OptimizingCompilerExceptions (leave it up to caller to decide what to + * do) Precondition: compilationInProgress "lock" has been acquired + * + * @param method + * the method to compile + * @param plan + * the plan to use for compiling the method + */ + private static VM_CompiledMethod optCompile(VM_NormalMethod method, + OPT_CompilationPlan plan) throws OPT_OptimizingCompilerException { + if (VM.BuildForOptCompiler) { + if (VM.VerifyAssertions) { + VM._assert(compilationInProgress, + "Failed to acquire compilationInProgress \"lock\""); + } + + VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.JNI); + long start = 0; + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + start = VM_Thread.getCurrentThread().accumulateCycles(); + } + + VM_CompiledMethod cm = OPT_Compiler.compile(plan); + + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + long end = VM_Thread.getCurrentThread().accumulateCycles(); + double compileTime = VM_Time.cyclesToMillis(end - start); + cm.setCompilationTime(compileTime); + record(OPT_COMPILER, method, cm); + } + + return cm; + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return null; + } + } + + // These methods are safe to invoke from VM_RuntimeCompiler.compile + + /** + * This method tries to compile the passed method with the OPT_Compiler, using + * the default compilation plan. If this fails we will use the quicker + * compiler (baseline for now) The following is carefully crafted to avoid + * (infinte) recursive opt compilation for all combinations of bootimages & + * lazy/eager compilation. Be absolutely sure you know what you're doing + * before changing it !!! + * + * @param method + * the method to compile + */ + public static synchronized VM_CompiledMethod optCompileWithFallBack( + VM_NormalMethod method) { + if (VM.BuildForOptCompiler) { + if (compilationInProgress) { + return fallback(method); + } else { + try { + compilationInProgress = true; + OPT_CompilationPlan plan = new OPT_CompilationPlan(method, + (OPT_OptimizationPlanElement[]) optimizationPlan, null, + (OPT_Options) options); + return optCompileWithFallBackInternal(method, plan); + } finally { + compilationInProgress = false; + } + } + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return null; + } + } + + /** + * This method tries to compile the passed method with the OPT_Compiler with + * the passed compilation plan. If this fails we will use the quicker compiler + * (baseline for now) The following is carefully crafted to avoid (infinte) + * recursive opt compilation for all combinations of bootimages & lazy/eager + * compilation. Be absolutely sure you know what you're doing before changing + * it !!! + * + * @param method + * the method to compile + * @param plan + * the compilation plan to use for the compile + */ + public static synchronized VM_CompiledMethod optCompileWithFallBack( + VM_NormalMethod method, OPT_CompilationPlan plan) { + if (VM.BuildForOptCompiler) { + if (compilationInProgress) { + return fallback(method); + } else { + try { + compilationInProgress = true; + return optCompileWithFallBackInternal(method, plan); + } finally { + compilationInProgress = false; + } + } + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return null; + } + } + + /** + * This real method that performs the opt compilation. + * + * @param method + * the method to compile + * @param plan + * the compilation plan to use + */ + private static VM_CompiledMethod optCompileWithFallBackInternal( + VM_NormalMethod method, OPT_CompilationPlan plan) { + if (VM.BuildForOptCompiler) { + if (method.hasNoOptCompileAnnotation()) + return fallback(method); + try { + return optCompile(method, plan); + } catch (OPT_OptimizingCompilerException e) { + String msg = "VM_RuntimeCompiler: can't optimize \"" + method + + "\" (error was: " + e + "): reverting to baseline compiler\n"; + if (e.isFatal && VM.ErrorsFatal) { + e.printStackTrace(); + VM.sysFail(msg); + } else { + boolean printMsg = true; + if (e instanceof OPT_MagicNotImplementedException) { + printMsg = !((OPT_MagicNotImplementedException) e).isExpected; + } + if (printMsg) + VM.sysWrite(msg); + } + return fallback(method); + } + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return null; + } + } + + /* recompile the specialized method with OPT_Compiler. */ + public static VM_CompiledMethod recompileWithOptOnStackSpecialization( + OPT_CompilationPlan plan) { + if (VM.BuildForOptCompiler) { + if (VM.VerifyAssertions) { + VM._assert(plan.method.isForOsrSpecialization()); + } + if (compilationInProgress) { + return null; + } + + try { + compilationInProgress = true; + + // the compiler will check if isForOsrSpecialization of the method + VM_CompiledMethod cm = optCompile(plan.method, plan); + + // we donot replace the compiledMethod of original method, + // because it is temporary method + return cm; + } catch (OPT_OptimizingCompilerException e) { + e.printStackTrace(); + String msg = "Optimizing compiler " + + "(via recompileWithOptOnStackSpecialization): " + + "can't optimize \"" + plan.method + "\" (error was: " + e + ")\n"; + + if (e.isFatal && VM.ErrorsFatal) { + VM.sysFail(msg); + } else { + VM.sysWrite(msg); + } + return null; + } finally { + compilationInProgress = false; + } + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return null; + } + } + + /** + * This method tries to compile the passed method with the OPT_Compiler. It + * will install the new compiled method in the VM, if sucessful. NOTE: the + * recompile method should never be invoked via VM_RuntimeCompiler.compile; it + * does not have sufficient guards against recursive recompilation. + * + * @param plan + * the compilation plan to use + * @return the CMID of the new method if successful, -1 if the recompilation + * failed. + * + */ + public static synchronized int recompileWithOpt(OPT_CompilationPlan plan) { + if (VM.BuildForOptCompiler) { + if (compilationInProgress) { + return -1; + } else { + try { + compilationInProgress = true; + VM_CompiledMethod cm = optCompile(plan.method, plan); + try { + plan.method.replaceCompiledMethod(cm); + } catch (Throwable e) { + String msg = "Failure in VM_Method.replaceCompiledMethod (via recompileWithOpt): while replacing \"" + + plan.method + "\" (error was: " + e + ")\n"; + if (VM.ErrorsFatal) { + e.printStackTrace(); + VM.sysFail(msg); + } else { + VM.sysWrite(msg); + } + return -1; + } + return cm.getId(); + } catch (OPT_OptimizingCompilerException e) { + String msg = "Optimizing compiler (via recompileWithOpt): can't optimize \"" + + plan.method + "\" (error was: " + e + ")\n"; + if (e.isFatal && VM.ErrorsFatal) { + e.printStackTrace(); + VM.sysFail(msg); + } else { + // VM.sysWrite(msg); + } + return -1; + } finally { + compilationInProgress = false; + } + } + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return -1; + } + } + + /** + * A wrapper method for those callers who don't want to make optimization + * plans + * + * @param method + * the method to recompile + */ + public static int recompileWithOpt(VM_NormalMethod method) { + if (VM.BuildForOptCompiler) { + OPT_CompilationPlan plan = new OPT_CompilationPlan(method, + (OPT_OptimizationPlanElement[]) optimizationPlan, null, + (OPT_Options) options); + return recompileWithOpt(plan); + } else { + if (VM.VerifyAssertions) + VM._assert(false); + return -1; + } + } + + /** + * This method uses the default compiler (baseline) to compile a method It is + * typically called when a more aggressive compilation fails. This method is + * safe to invoke from VM_RuntimeCompiler.compile + */ + protected static VM_CompiledMethod fallback(VM_NormalMethod method) { + // call the inherited method "baselineCompile" + return baselineCompile(method); + } + + public static void boot() { + if (VM.MeasureCompilation) { + VM_Callbacks.addExitMonitor(new VM_RuntimeCompiler()); + } + if (VM.BuildForAdaptiveSystem) { + options = new OPT_Options(); + optimizationPlan = OPT_OptimizationPlanner + .createOptimizationPlan((OPT_Options) options); + if (VM.MeasureCompilation) { + OPT_OptimizationPlanner.initializeMeasureCompilation(); + } + + OPT_Compiler.init((OPT_Options) options); + + VM_PreCompile.init(); + // when we reach here the OPT compiler is enabled. + compilerEnabled = true; + + for (int i = 0; i < earlyOptArgs.length; i += 2) { + processOptCommandLineArg(earlyOptArgs[i], earlyOptArgs[i + 1]); + } + } + } + + public static void processCommandLineArg(String prefix, String arg) { + if (VM.BuildForAdaptiveSystem) { + if (VM_Controller.options != null && VM_Controller.options.optIRC()) { + processOptCommandLineArg(prefix, arg); + } else { + VM_BaselineCompiler.processCommandLineArg(prefix, arg); + } + } else { + VM_BaselineCompiler.processCommandLineArg(prefix, arg); + } + } + + /** + * Compile a Java method when it is first invoked. + * + * @param method + * the method to compile + * @return its compiled method. + */ + public static VM_CompiledMethod compile(VM_NormalMethod method) { + if (VM.BuildForAdaptiveSystem) { + VM_CompiledMethod cm; + if (!VM_Controller.enabled) { + // System still early in boot process; compile with baseline compiler + cm = baselineCompile(method); + VM_ControllerMemory.incrementNumBase(); + } else { + if (!preloadChecked) { + preloadChecked = true; // prevent subsequent calls + // N.B. This will use irc options + if (VM_BaselineCompiler.options.PRELOAD_CLASS != null) { + compilationInProgress = true; // use baseline during preload + // Other than when boot options are requested (processed during + // preloadSpecialClass + // It is hard to communicate options for these special compilations. + // Use the + // default options and at least pick up the verbose if requested for + // base/irc + OPT_Options tmpoptions = (OPT_Options) ((OPT_Options) options) + .clone(); + tmpoptions.PRELOAD_CLASS = VM_BaselineCompiler.options.PRELOAD_CLASS; + tmpoptions.PRELOAD_AS_BOOT = VM_BaselineCompiler.options.PRELOAD_AS_BOOT; + if (VM_BaselineCompiler.options.PRINT_METHOD) { + tmpoptions.PRINT_METHOD = true; + } else { + tmpoptions = (OPT_Options) options; + } + OPT_Compiler.preloadSpecialClass(tmpoptions); + compilationInProgress = false; + } + } + if (VM_Controller.options.optIRC() || method.optCompileOnly()) { + if (// will only run once: don't bother optimizing + method.isClassInitializer() || + // exception in progress. can't use opt compiler: + // it uses exceptions and runtime doesn't support + // multiple pending (undelivered) exceptions [--DL] + VM_Thread.getCurrentThread().hardwareExceptionRegisters.inuse) { + // compile with baseline compiler + cm = baselineCompile(method); + VM_ControllerMemory.incrementNumBase(); + } else { // compile with opt compiler + VM_AOSInstrumentationPlan instrumentationPlan = new VM_AOSInstrumentationPlan( + VM_Controller.options, method); + OPT_CompilationPlan compPlan = new OPT_CompilationPlan(method, + (OPT_OptimizationPlanElement[]) optimizationPlan, + instrumentationPlan, (OPT_Options) options); + if (!method.optCompileOnly()) { + cm = optCompileWithFallBack(method, compPlan); + } else { + compilationInProgress = true; + try { + cm = optCompile(method, compPlan); + } catch (OPT_OptimizingCompilerException e) { + String msg = "Optimizing compiler " + + "(on method that can only be optimizing compiler compiled): " + + "can't optimize \"" + method + "\""; + throw new Error(msg, e); + } finally { + compilationInProgress = false; + } + } + } + } else { + if ((VM_Controller.options.BACKGROUND_RECOMPILATION + && (!VM_Controller.options.ENABLE_REPLAY_COMPILE) && (!VM_Controller.options.ENABLE_PRECOMPILE))) { + // must be an inital compilation: compile with baseline compiler + // or if recompilation with OSR. + cm = baselineCompile(method); + VM_ControllerMemory.incrementNumBase(); + } else { + if (VM_CompilerAdviceAttribute.hasAdvice()) { + VM_CompilerAdviceAttribute attr = VM_CompilerAdviceAttribute + .getCompilerAdviceInfo(method); + if (attr.getCompiler() != VM_CompiledMethod.OPT) { + cm = fallback(method); + VM_AOSLogging.recordCompileTime(cm, 0.0); + return cm; + } + int newCMID = -2; + OPT_CompilationPlan compPlan; + if (VM_Controller.options.counters()) { + // for invocation counter, we only use one optimization level + compPlan = VM_InvocationCounts.createCompilationPlan(method); + } else { + // for now there is not two options for sampling, so + // we don't have to use: if (VM_Controller.options.sampling()) + compPlan = VM_Controller.recompilationStrategy + .createCompilationPlan(method, attr.getOptLevel(), null); + } + VM_AOSLogging.recompilationStarted(compPlan); + newCMID = recompileWithOpt(compPlan); + cm = newCMID == -1 ? null : VM_CompiledMethods + .getCompiledMethod(newCMID); + if (newCMID == -1) { + VM_AOSLogging.recompilationAborted(compPlan); + } else if (newCMID > 0) { + VM_AOSLogging.recompilationCompleted(compPlan); + } + if (cm == null) { // if recompilation is aborted + cm = baselineCompile(method); + VM_ControllerMemory.incrementNumBase(); + } + } else { + // check to see if there is a compilation plan for this method. + VM_ControllerPlan plan = VM_ControllerMemory + .findLatestPlan(method); + if (plan == null + || plan.getStatus() != VM_ControllerPlan.IN_PROGRESS) { + // initial compilation or some other funny state: compile with + // baseline compiler + cm = baselineCompile(method); + VM_ControllerMemory.incrementNumBase(); + } else { + cm = plan.doRecompile(); + if (cm == null) { + // opt compilation aborted for some reason. + cm = baselineCompile(method); + } + } + } + } + } + } + if ((VM_Controller.options.ENABLE_ADVICE_GENERATION) + && (cm.getCompilerType() == VM_CompiledMethod.BASELINE) + && VM_Controller.enabled) { + VM_AOSGenerator.baseCompilationCompleted(cm); + } + VM_AOSLogging.recordCompileTime(cm, 0.0); + return cm; + } else { + return baselineCompile(method); + } + } + + /** + * Compile the stub for a native method when it is first invoked. + * + * @param method + * the method to compile + * @return its compiled method. + */ + public static VM_CompiledMethod compile(VM_NativeMethod method) { + VM_Callbacks.notifyMethodCompile(method, VM_CompiledMethod.JNI); + long start = 0; + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + start = VM_Thread.getCurrentThread().accumulateCycles(); + } + + VM_CompiledMethod cm = VM_JNICompiler.compile(method); + if (VM.verboseJNI) { + VM.sysWriteln("[Dynamic-linking native method " + + method.getDeclaringClass() + "." + method.getName() + " " + + method.getDescriptor()); + } + + if (VM.MeasureCompilation || VM.BuildForAdaptiveSystem) { + long end = VM_Thread.getCurrentThread().accumulateCycles(); + double compileTime = VM_Time.cyclesToMillis(end - start); + cm.setCompilationTime(compileTime); + record(JNI_COMPILER, method, cm); + } + + return cm; + } + + /** + * returns the string version of compiler number, using the naming scheme in + * this file + * + * @param compiler + * the compiler of interest + * @return the string version of compiler number + */ + public static String getCompilerName(byte compiler) { + return name[compiler]; + } + +} Copied: ext/org/jikesrvm/compilers/opt (from rev 16, ext/org/jikesrvm/opt) Modified: ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java =================================================================== --- ext/org/jikesrvm/opt/OPT_Simplifier.java 2007-03-31 14:04:36 UTC (rev 16) +++ ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-04-02 12:11:23 UTC (rev 19) @@ -6,130 +6,138 @@ * * (C) Copyright IBM Corp. 2001 */ -package org.jikesrvm.opt; +package org.jikesrvm.compilers.opt; import org.jikesrvm.classloader.*; +import org.jikesrvm.compilers.opt.ir.*; +import org.jikesrvm.objectmodel.VM_TIBLayoutConstants; import org.jikesrvm.VM; -import org.jikesrvm.VM_TIBLayoutConstants; -import org.jikesrvm.opt.ir.*; import org.vmmagic.unboxed.*; import java.lang.reflect.Array; import static org.jikesrvm.VM_SizeConstants.*; -import static org.jikesrvm.opt.ir.OPT_Operators.*; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; + /** - * A constant folder, strength reducer and axiomatic simplifier. - * - * <p> This module performs no analysis, it simply attempts to - * simplify the instruction as is. The intent is that - * analysis modules can call this transformation engine, allowing us to - * share the tedious simplification code among multiple analysis modules. - * - * <p> NOTE: For maintainability purposes, I've intentionally avoided being - * clever about combining 'similar' operators together into a combined case - * of the main switch switch statement. Also, operators are in sorted ordered - * within each major grouping. Please maintain this coding style. - * I'd rather have this module be 2000 lines of obviously correct code than - * 500 lines of clever code. - * + * A constant folder, strength reducer and axiomatic simplifier. + * + * <p> + * This module performs no analysis, it simply attempts to simplify the + * instruction as is. The intent is that analysis modules can call this + * transformation engine, allowing us to share the tedious simplification code + * among multiple analysis modules. + * + * <p> + * NOTE: For maintainability purposes, I've intentionally avoided being clever + * about combining 'similar' operators together into a combined case of the main + * switch switch statement. Also, operators are in sorted ordered within each + * major grouping. Please maintain this coding style. I'd rather have this + * module be 2000 lines of obviously correct code than 500 lines of clever code. + * * @author Dave Grove * @author Ian Rogers */ public abstract class OPT_Simplifier extends OPT_IRTools { // NOTE: The convention is that constant folding is controlled based // on the type of the result of the operator, not the type of its inputs. - /** + /** * Constant fold integer operations? */ public static final boolean CF_INT = true; - /** + + /** * Constant fold address operations? */ public static final boolean CF_LONG = true; - /** + /** * Constant fold address operations? */ public static final boolean CF_ADDR = true; - /** - * Constant fold float operations? Default is true, flip to avoid - * consuming precious JTOC slots to hold new constant values. + /** + * Constant fold float operations? Default is true, flip to avoid consuming + * precious JTOC slots to hold new constant values. */ public static final boolean CF_FLOAT = true; - /** - * Constant fold double operations? Default is true, flip to avoid - * consuming precious JTOC slots to hold new constant values. + + /** + * Constant fold double operations? Default is true, flip to avoid consuming + * precious JTOC slots to hold new constant values. */ public static final boolean CF_DOUBLE = true; - /** - * Constant fold field operations? Default is true, flip to avoid - * consuming precious JTOC slots to hold new constant values. + + /** + * Constant fold field operations? Default is true, flip to avoid consuming + * precious JTOC slots to hold new constant values. */ public static final boolean CF_FIELDS = false; - /** - * Constant fold TIB operations? Default is true, flip to avoid - * consuming precious JTOC slots to hold new constant values. + /** + * Constant fold TIB operations? Default is true, flip to avoid consuming + * precious JTOC slots to hold new constant values. */ public static final boolean CF_TIB = false; /** * Effect of the simplification on Def-Use chains */ - public enum DefUseEffect{ + public enum DefUseEffect { /** - * Enumeration value to indicate an operation is unchanged, - * although the order of operands may have been canonicalized and - * type information strengthened. + * Enumeration value to indicate an operation is unchanged, although the + * order of operands may have been canonicalized and type information + * strengthened. */ UNCHANGED, /** - * Enumeration value to indicate an operation has been replaced by - * a move instruction with a constant right hand side. + * Enumeration value to indicate an operation has been replaced by a move + * instruction with a constant right hand side. */ MOVE_FOLDED, /** - * Enumeration value to indicate an operation has been replaced by - * a move instruction with a non-constant right hand side. + * Enumeration value to indicate an operation has been replaced by a move + * instruction with a non-constant right hand side. */ MOVE_REDUCED, /** - * Enumeration value to indicate an operation has been replaced by - * an unconditional trap instruction. + * Enumeration value to indicate an operation has been replaced by an + * unconditional trap instruction. */ TRAP_REDUCED, /** - * Enumeration value to indicate an operation has been replaced by - * a cheaper, but non-move instruction. + * Enumeration value to indicate an operation has been replaced by a + * cheaper, but non-move instruction. */ REDUCED - } + } /** - * Given an instruction, attempt to simplify it. - * The instruction will be mutated in place. - * - * <p> We don't deal with branching operations here -- - * doing peephole optimizations of branches - * is the job of a separate module. - * - * @param regpool register pool in case simplification requires a temporary register - * @param s the instruction to simplify + * Given an instruction, attempt to simplify it. The instruction will be + * mutated in place. + * + * <p> + * We don't deal with branching operations here -- doing peephole + * optimizations of branches is the job of a separate module. + * + * @param regpool + * register pool in case simplification requires a temporary register + * @param s + * the instruction to simplify * @return one of UNCHANGED, MOVE_FOLDED, MOVE_REDUCED, TRAP_REDUCED, REDUCED */ - public static DefUseEffect simplify(OPT_AbstractRegisterPool regpool, OPT_Instruction s) { + public static DefUseEffect simplify(OPT_AbstractRegisterPool regpool, + OPT_Instruction s) { DefUseEffect result; char opcode = s.getOpcode(); switch (opcode) { - //////////////////// - // GUARD operations - //////////////////// + // ////////////////// + // GUARD operations + // ////////////////// case GUARD_COMBINE_opcode: result = guardCombine(s); break; - //////////////////// - // TRAP operations - //////////////////// + // ////////////////// + // TRAP operations + // ////////////////// case TRAP_IF_opcode: result = trapIf(s); break; @@ -166,9 +174,9 @@ case MUST_IMPLEMENT_INTERFACE_opcode: result = mustImplementInterface(s); break; - //////////////////// - // Conditional moves - //////////////////// + // ////////////////// + // Conditional moves + // ////////////////// case INT_COND_MOVE_opcode: result = intCondMove(s); break; @@ -187,9 +195,9 @@ case GUARD_COND_MOVE_opcode: result = guardCondMove(s); break; - //////////////////// - // INT ALU operations - //////////////////// + // ////////////////// + // INT ALU operations + // ////////////////// case BOOLEAN_NOT_opcode: result = booleanNot(s); break; @@ -202,9 +210,9 @@ case BOOLEAN_CMP2_INT_OR_opcode: result = booleanCmp2IntOr(s); break; - //case BOOLEAN_CMP2_INT_AND: - //result = booleanCmp2IntAnd(s); - //break; + // case BOOLEAN_CMP2_INT_AND: + // result = booleanCmp2IntAnd(s); + // break; case INT_ADD_opcode: result = intAdd(s); break; @@ -244,9 +252,9 @@ case INT_XOR_opcode: result = intXor(s); break; - //////////////////// - // WORD ALU operations - //////////////////// + // ////////////////// + // WORD ALU operations + // ////////////////// case REF_ADD_opcode: result = refAdd(s); break; @@ -274,9 +282,9 @@ case REF_XOR_opcode: result = refXor(s); break; - //////////////////// - // LONG ALU operations - //////////////////// + // ////////////////// + // LONG ALU operations + // ////////////////// case LONG_ADD_opcode: result = longAdd(s); break; @@ -319,9 +327,9 @@ case LONG_XOR_opcode: result = longXor(s); break; - //////////////////// - // FLOAT ALU operations - //////////////////// + // ////////////////// + // FLOAT ALU operations + // ////////////////// case FLOAT_ADD_opcode: result = floatAdd(s); break; @@ -346,9 +354,9 @@ case FLOAT_SUB_opcode: result = floatSub(s); break; - //////////////////// - // DOUBLE ALU operations - //////////////////// + // ////////////////// + // DOUBLE ALU operations + // ////////////////// case DOUBLE_ADD_opcode: result = doubleAdd(s); break; @@ -373,9 +381,9 @@ case DOUBLE_SUB_opcode: result = doubleSub(s); break; - //////////////////// - // CONVERSION operations - //////////////////// + // ////////////////// + // CONVERSION operations + // ////////////////// case DOUBLE_2FLOAT_opcode: result = double2Float(s); break; @@ -448,9 +456,9 @@ case LONG_BITS_AS_DOUBLE_opcode: result = longBitsAsDouble(s); break; - //////////////////// - // Field operations - //////////////////// + // ////////////////// + // Field operations + // ////////////////// case ARRAYLENGTH_opcode: result = arrayLength(s); break; @@ -488,28 +496,28 @@ result = DefUseEffect.UNCHANGED; } if (VM.VerifyAssertions) { - switch (result) { - case MOVE_FOLDED: - // Check move has constant RHS - VM._assert(Move.conforms(s) && - (Move.getVal(s) instanceof OPT_ConstantOperand), - "RHS of move " + s + " should be constant during simplification of " - + OPT_OperatorNames.operatorName[opcode]); - break; - case MOVE_REDUCED: - // Check move has non-constant RHS - VM._assert(Move.conforms(s) && - !(Move.getVal(s) instanceof OPT_ConstantOperand), - "RHS of move " + s + " shouldn't be constant during simplification of " - + OPT_OperatorNames.operatorName[opcode]); - break; - default: - // Nothing to check - } + switch (result) { + case MOVE_FOLDED: + // Check move has constant RHS + VM._assert(Move.conforms(s) + && (Move.getVal(s) instanceof OPT_ConstantOperand), "RHS of move " + + s + " should be constant during simplification of " + + OPT_OperatorNames.operatorName[opcode]); + break; + case MOVE_REDUCED: + // Check move has non-constant RHS + VM._assert(Move.conforms(s) + && !(Move.getVal(s) instanceof OPT_ConstantOperand), "RHS of move " + + s + " shouldn't be constant during simplification of " + + OPT_OperatorNames.operatorName[opcode]); + break; + default: + // Nothing to check + } } return result; } - + private static DefUseEffect guardCombine(OPT_Instruction s) { OPT_Operand op1 = Binary.getVal1(s); OPT_Operand op2 = Binary.getVal2(s); @@ -522,26 +530,25 @@ // ONLY OP2 IS TrueGuard: MOVE REDUCE return DefUseEffect.MOVE_REDUCED; } - } - else if(op1 instanceof OPT_TrueGuardOperand) { + } else if (op1 instanceof OPT_TrueGuardOperand) { // ONLY OP1 IS TrueGuard: MOVE REDUCE Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op2); return DefUseEffect.MOVE_REDUCED; - } - else { + } else { return DefUseEffect.UNCHANGED; } } + private static DefUseEffect trapIf(OPT_Instruction s) { - { + { OPT_Operand op1 = TrapIf.getVal1(s); OPT_Operand op2 = TrapIf.getVal2(s); if (op1.isConstant()) { if (op2.isConstant()) { int willTrap = TrapIf.getCond(s).evaluate(op1, op2); if (willTrap == OPT_ConditionOperand.TRUE) { - Trap.mutate(s, TRAP, TrapIf.getClearGuardResult(s), - TrapIf.getClearTCode(s)); + Trap.mutate(s, TRAP, TrapIf.getClearGuardResult(s), TrapIf + .getClearTCode(s)); return DefUseEffect.TRAP_REDUCED; } else if (willTrap == OPT_ConditionOperand.FALSE) { Move.mutate(s, GUARD_MOVE, TrapIf.getClearGuardResult(s), TG()); @@ -549,44 +556,43 @@ } } else { // canonicalize - TrapIf.mutate(s, TRAP_IF, TrapIf.getClearGuardResult(s), - TrapIf.getClearVal2(s), - TrapIf.getClearVal1(s), - TrapIf.getClearCond(s).flipOperands(), - TrapIf.getClearTCode(s)); + TrapIf.mutate(s, TRAP_IF, TrapIf.getClearGuardResult(s), TrapIf + .getClearVal2(s), TrapIf.getClearVal1(s), TrapIf.getClearCond(s) + .flipOperands(), TrapIf.getClearTCode(s)); } } - } + } return DefUseEffect.UNCHANGED; } + private static DefUseEffect nullCheck(OPT_Instruction s) { - OPT_Operand ref = NullCheck.getRef(s); - if (ref.isNullConstant() || - (ref.isAddressConstant() && ref.asAddressConstant().value.isZero())) { - Trap.mutate(s, TRAP, NullCheck.getClearGuardResult(s), - OPT_TrapCodeOperand.NullPtr()); - return DefUseEffect.TRAP_REDUCED; - } else if (ref.isConstant()) { - // object, string, class or non-null address constant - - // Make the slightly suspect assumption that all non-zero address - // constants are actually valid pointers. Not necessarily true, - // but unclear what else we can do. - Move.mutate(s, GUARD_MOVE, NullCheck.getClearGuardResult(s), TG()); - return DefUseEffect.MOVE_FOLDED; - } - else { - return DefUseEffect.UNCHANGED; - } + OPT_Operand ref = NullCheck.getRef(s); + if (ref.isNullConstant() + || (ref.isAddressConstant() && ref.asAddressConstant().value.isZero())) { + Trap.mutate(s, TRAP, NullCheck.getClearGuardResult(s), + OPT_TrapCodeOperand.NullPtr()); + return DefUseEffect.TRAP_REDUCED; + } else if (ref.isConstant()) { + // object, string, class or non-null address constant + + // Make the slightly suspect assumption that all non-zero address + // constants are actually valid pointers. Not necessarily true, + // but unclear what else we can do. + Move.mutate(s, GUARD_MOVE, NullCheck.getClearGuardResult(s), TG()); + return DefUseEffect.MOVE_FOLDED; + } else { + return DefUseEffect.UNCHANGED; + } } + private static DefUseEffect intZeroCheck(OPT_Instruction s) { - { + { OPT_Operand op = ZeroCheck.getValue(s); if (op.isIntConstant()) { int val = op.asIntConstant().value; if (val == 0) { Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), - OPT_TrapCodeOperand.DivByZero()); + OPT_TrapCodeOperand.DivByZero()); return DefUseEffect.TRAP_REDUCED; } else { Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG()); @@ -596,14 +602,15 @@ } return DefUseEffect.UNCHANGED; } + private static DefUseEffect longZeroCheck(OPT_Instruction s) { - { + { OPT_Operand op = ZeroCheck.getValue(s); if (op.isLongConstant()) { long val = op.asLongConstant().value; if (val == 0L) { Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), - OPT_TrapCodeOperand.DivByZero()); + OPT_TrapCodeOperand.DivByZero()); return DefUseEffect.TRAP_REDUCED; } else { Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG()); @@ -613,7 +620,9 @@ } return DefUseEffect.UNCHANGED; } - private static DefUseEffect checkcast(OPT_AbstractRegisterPool regpool, OPT_Instruction s) { + + private static DefUseEffect checkcast(OPT_AbstractRegisterPool regpool, + OPT_Instruction s) { OPT_Operand ref = TypeCheck.getRef(s); if (ref.isNullConstant()) { Empty.mutate(s, NOP); @@ -634,6 +643,7 @@ } } } + private static DefUseEffect checkcastNotNull(OPT_Instruction s) { OPT_Operand ref = TypeCheck.getRef(s); VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); @@ -645,18 +655,20 @@ } else if (ans == OPT_Constants.NO) { VM_Type rType = rhsType.peekResolvedType(); if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { - // only final (or precise) rhs types can be optimized since rhsType may be conservative + // only final (or precise) rhs types can be optimized since rhsType may + // be conservative Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.CheckCast()); return DefUseEffect.TRAP_REDUCED; } else { return DefUseEffect.UNCHANGED; } - } - else { + } else { return DefUseEffect.UNCHANGED; } } - private static DefUseEffect instanceOf(OPT_AbstractRegisterPool regpool, OPT_Instruction s) { + + private static DefUseEffect instanceOf(OPT_AbstractRegisterPool regpool, + OPT_Instruction s) { OPT_Operand ref = InstanceOf.getRef(s); if (ref.isNullConstant()) { Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); @@ -668,25 +680,26 @@ VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef(); VM_TypeReference rhsType = ref.getType(); byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); - // NOTE: OPT_Constants.YES doesn't help because ref may be null and null instanceof T is false + // NOTE: OPT_Constants.YES doesn't help because ref may be null and null + // instanceof T is false if (ans == OPT_Constants.NO) { VM_Type rType = rhsType.peekResolvedType(); if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { - // only final (or precise) rhs types can be optimized since rhsType may be conservative + // only final (or precise) rhs types can be optimized since rhsType + // may be conservative Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); return DefUseEffect.MOVE_FOLDED; - } - else { + } else { return DefUseEffect.UNCHANGED; } - } - else { + } else { return DefUseEffect.UNCHANGED; } } } + private static DefUseEffect instanceOfNotNull(OPT_Instruction s) { - { + { OPT_Operand ref = InstanceOf.getRef(s); VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef(); VM_TypeReference rhsType = ref.getType(); @@ -697,7 +710,8 @@ } else if (ans == OPT_Constants.NO) { VM_Type rType = rhsType.peekResolvedType(); if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { - // only final (or precise) rhs types can be optimized since rhsType may be conservative + // only final (or precise) rhs types can be optimized since rhsType + // may be conservative Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); return DefUseEffect.MOVE_FOLDED; } @@ -705,103 +719,118 @@ } return DefUseEffect.UNCHANGED; } - private static DefUseEffect objarrayStoreCheck(OPT_Instruction s){ + + private static DefUseEffect objarrayStoreCheck(OPT_Instruction s) { OPT_Operand val = StoreCheck.getVal(s); if (val.isNullConstant()) { // Writing null into an array is trivially safe - Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck + .getClearGuard(s)); return DefUseEffect.MOVE_REDUCED; - } - else { + } else { OPT_Operand ref = StoreCheck.getRef(s); VM_TypeReference arrayTypeRef = ref.getType(); - VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType().peekResolvedType(); + VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType() + .peekResolvedType(); if (typeOfIMElem != null) { VM_Type typeOfVal = val.getType().peekResolvedType(); - if ((typeOfIMElem == typeOfVal) && - (typeOfIMElem.isPrimitiveType() || - typeOfIMElem.asClass().isFinal())) { + if ((typeOfIMElem == typeOfVal) + && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass() + .isFinal())) { // Writing something of a final type to an array of that // final type is safe Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), - StoreCheck.getClearGuard(s)); + StoreCheck.getClearGu... [truncated message content] |
From: <mic...@us...> - 2007-04-11 21:25:11
|
Revision: 25 http://svn.sourceforge.net/pearcolator/?rev=25&view=rev Author: michael_baer Date: 2007-04-11 14:25:11 -0700 (Wed, 11 Apr 2007) Log Message: ----------- Moved memory access functions from interface LinuxSystemCallGenerator to the Memory class Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-11 21:25:11 UTC (rev 25) @@ -231,7 +231,7 @@ */ public PPC_InstructionDecoder interpretInstruction(PPC_ProcessSpace ps) throws BadInstructionException { - ps.currentInstruction = ps.memoryLoad32(ps.getCurrentInstructionAddress()); + ps.currentInstruction = ps.memory.load32(ps.getCurrentInstructionAddress()); try { return getDecoder(ps.currentInstruction).interpretInstruction(ps); } catch (NullPointerException e) { @@ -246,7 +246,7 @@ protected static PPC_InstructionDecoder moveInstructionOnAndReturnDecoder( PPC_ProcessSpace ps) { ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + 4); - ps.currentInstruction = ps.memoryLoad32(ps.getCurrentInstructionAddress()); + ps.currentInstruction = ps.memory.load32(ps.getCurrentInstructionAddress()); return findDecoder(ps.currentInstruction); } @@ -264,7 +264,7 @@ */ public static int translateInstruction(PPC2IR ppc2ir, PPC_ProcessSpace ps, PPC_Laziness lazy, int pc) { - int instr = ps.memoryLoad32(pc); + int instr = ps.memory.load32(pc); if (DBT_Options.debugInstr) { System.out.println(lazy.makeKey(pc) + PPC_Disassembler.disasm(instr, pc) @@ -3593,7 +3593,7 @@ int d = EXTS(bits(ps.currentInstruction, 16, 31), 16); int EA = (rA == 0) ? d : (ps.getRegister(rA) + d); int value = Float.floatToIntBits((float) ps.getFPregister(frS)); - ps.memoryStore32(EA, value); + ps.memory.store32(EA, value); return moveInstructionOnAndReturnDecoder(ps); } @@ -3654,7 +3654,7 @@ int d = EXTS(bits(ps.currentInstruction, 16, 31), 16); int EA = (rA == 0) ? d : (ps.getRegister(rA) + d); int value = Float.floatToIntBits((float) ps.getFPregister(frS)); - ps.memoryStore32(EA, value); + ps.memory.store32(EA, value); ps.setRegister(rA, EA); return moveInstructionOnAndReturnDecoder(ps); } @@ -3965,7 +3965,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -4626,7 +4626,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -11662,7 +11662,7 @@ } } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } @@ -11806,7 +11806,7 @@ .getCurrentInstructionAddress() + 4, target_address); } ps.setCurrentInstructionAddress(target_address); - ps.currentInstruction = ps.memoryLoad32(target_address); + ps.currentInstruction = ps.memory.load32(target_address); return findDecoder(ps.currentInstruction); } Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -992,7 +992,7 @@ * Run a single instruction */ public void runOneInstruction() throws BadInstructionException { - currentInstruction = memoryLoad32(pc); + currentInstruction = memory.load32(pc); try { PPC_InstructionDecoder.findDecoder(currentInstruction) .interpretInstruction(this); Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Simulate the process address space for our PowerPC ELF binary. Also keep @@ -203,4 +204,8 @@ return false; } + public ProcessSpace getProcessSpace() { + return this; + } + } Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Linux specific parts of the process @@ -166,4 +167,8 @@ public byte[] getPlatformString() { return new byte[] {'\0', '6', '8', '6', 'i'}; } + + public ProcessSpace getProcessSpace() { + return this; + } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-11 21:25:11 UTC (rev 25) @@ -9,6 +9,7 @@ package org.binarytranslator.generic.os.abi.linux; import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Class encapsulating the interface between Linux system calls and @@ -56,39 +57,13 @@ * @param address where to write * @param data value to store */ - public void memoryStore32(int address, int data); + /** - * Write to the memory of the system call generator an 8bit value - * @param address where to write - * @param data value to store - */ - public void memoryStore8(int address, byte data); + * Returns the process space that this call originated from. + */ + public ProcessSpace getProcessSpace(); + /** - * Load from memory of the system call generator an 8bit value - * @param address where to read - * @return value read - */ - public byte memoryLoad8(int address); - /** - * Load from memory of the system call generator a 32bit value - * @param address where to read - * @return value read - */ - public int memoryLoad32(int address); - /** - * Load an ASCIIZ string from the memory of the system call - * generator and return it as a Java String. - * @param address where to read - * @return the String read - */ - public String memoryReadString(int address); - /** - * Store an ASCIIZ string to the memory of the system call generator - * @param address where to read - * @param data the String to write - */ - public void memoryWriteString(int address, String data); - /** * Get the top of the BSS segment (the heap that reside below the * stack in memory) * @return top of BSS segment @@ -100,13 +75,4 @@ * @param address new top of BSS segment */ public void setBrk(int address); - /** - * Map an anonymous page of memory - * @param addr the address to map or NULL if don't care - * @param len the amount of memory to map - * @param read is the page readable - * @param write is the page writable - * @param exec is the page executable - */ - public int memoryMap(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException; } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-11 21:25:11 UTC (rev 25) @@ -10,6 +10,7 @@ import java.io.*; import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; import java.util.ArrayList; import java.net.InetAddress; @@ -62,7 +63,44 @@ * List of (RandomAccessFile(s)) files currently open */ private ArrayList<Object> files; + + /** + * Load an ASCIIZ string from the memory of the system call + * generator and return it as a Java String. + * @param address where to read + * @return the String read + */ + private String memoryReadString(int address) { + Memory m = src.getProcessSpace().memory; + + StringBuffer str = new StringBuffer(); + char c; + + while ((c = (char) m.loadUnsigned8(address++)) != 0) + str.append(c); + + return str.toString(); + } + + /** + * Store an ASCIIZ string to the memory of the system call generator + * @param address where to read + * @param data the String to write + */ + public void memoryWriteString(int address, String data) { + Memory m = src.getProcessSpace().memory; + + if (data != null) { + for (int i = 0; i < data.length(); i++) { + m.store8(address + i, (byte) data.charAt(i)); + } + + m.store8(address + data.length(), (byte) 0); + } + } + + /** * Convert integer file descriptor into Java RandomAccessFile */ private RandomAccessFile getRAFile(int fd) { @@ -489,13 +527,15 @@ int fd = arguments.nextInt(); int buf = arguments.nextInt(); int count = arguments.nextInt(); + + Memory mem = src.getProcessSpace().memory; if(fd == 0) { // read from stdin byte[] b = new byte[256]; try { int len = System.in.read(b); for (int i=0; i < len; i++) { - src.memoryStore32(buf + i, b[i]); + mem.store32(buf + i, b[i]); } src.setSysCallReturn(len); } @@ -518,7 +558,7 @@ while((b < count) && ((i = raFile.read()) != -1)) { byte by = (byte)i; b++; - src.memoryStore8(addr++, by); + mem.store8(addr++, by); } src.setSysCallReturn(b); // Return number of bytes read. } @@ -538,15 +578,17 @@ int fd = arguments.nextInt(); int buf = arguments.nextInt(); int count = arguments.nextInt(); + + Memory mem = src.getProcessSpace().memory; if(fd == 1) { // stdout for(int c = 0 ; c < count; c++) { - System.out.print((char) src.memoryLoad8(buf + c)); + System.out.print((char) mem.loadUnsigned8(buf + c)); } src.setSysCallReturn(count); } else if(fd == 2) { // sterr for(int c = 0 ; c < count ; c++) { - System.err.print((char) src.memoryLoad8(buf + c)); + System.err.print((char) mem.loadUnsigned8(buf + c)); } src.setSysCallReturn(count); } else { @@ -564,7 +606,7 @@ try { for(b = 1 ; b <= count ; b++) { - by = src.memoryLoad8(addr++); + by = (byte) mem.loadUnsigned8(addr++); raFile.write(by); } // Return number of bytes written, having accounted for b @@ -588,20 +630,21 @@ int fd = arguments.nextInt(); int vector = arguments.nextInt(); int count = arguments.nextInt(); + Memory mem = src.getProcessSpace().memory; if((fd == 1)||(fd == 2)) { // stdout || stderr - int base = src.memoryLoad32(vector); - int len = src.memoryLoad32(vector+4); + int base = mem.load32(vector); + int len = mem.load32(vector+4); int currentVector = 0; int curVectorPos = 0; for(int c = 0 ; c < count; c++) { if(curVectorPos == len) { currentVector++; - base = src.memoryLoad32(vector+(currentVector*8)); - len = src.memoryLoad32(vector+(currentVector*8)+4); + base = mem.load32(vector+(currentVector*8)); + len = mem.load32(vector+(currentVector*8)+4); curVectorPos = 0; } - System.out.print((char) src.memoryLoad8(base + curVectorPos)); + System.out.print((char) mem.loadUnsigned8(base + curVectorPos)); curVectorPos++; } src.setSysCallReturn(count); @@ -618,7 +661,7 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. - String fileName = src.memoryReadString(pathname); + String fileName = memoryReadString(pathname); // Create a File object so we can test for the existance and // properties of the file. @@ -760,12 +803,12 @@ hostName = localhostString.substring(0,index); } // Fill in utsname struct - see /usr/include/sys/utsname.h - src.memoryWriteString (addr, getSysName()); // sysname - src.memoryWriteString (addr+65, hostName); // nodename - src.memoryWriteString (addr+130, getRelease()); // release - src.memoryWriteString (addr+195, getVersion()); // version - src.memoryWriteString (addr+260, getMachine()); // machine - src.memoryWriteString (addr+325, domainName); // __domainname + memoryWriteString (addr, getSysName()); // sysname + memoryWriteString (addr+65, hostName); // nodename + memoryWriteString (addr+130, getRelease()); // release + memoryWriteString (addr+195, getVersion()); // version + memoryWriteString (addr+260, getMachine()); // machine + memoryWriteString (addr+325, domainName); // __domainname src.setSysCallReturn(0); } else { @@ -786,7 +829,9 @@ int offset = arguments.nextInt(); if((flags & mman.MAP_ANONYMOUS) != 0 ) { try { - src.setSysCallReturn(src.memoryMap(start, length, + Memory mem = src.getProcessSpace().memory; + + src.setSysCallReturn( mem.map(start, length, (prot & mman.PROT_READ) != 0, (prot & mman.PROT_WRITE) != 0, (prot & mman.PROT_EXEC) != 0)); Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 13:39:17 UTC (rev 24) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-11 21:25:11 UTC (rev 25) @@ -67,34 +67,6 @@ public Memory memory; /** - * Load a 32bit value from memory - */ - public int memoryLoad32(int wordAddr) { - return memory.load32(wordAddr); - } - - /** - * Store a 32bit value to memory - */ - public void memoryStore32(int address, int data) { - memory.store32(address, data); - } - - /** - * Load a 16bit value from memory - */ - public int memoryLoad16(int hwAddr) { - return memory.loadSigned16(hwAddr); - } - - /** - * Store a 16bit value to memory - */ - public void memoryStore16(int hwAddr, int iValue) { - memory.store16(hwAddr, iValue); - } - - /** * Load a 8bit value from memory */ public byte memoryLoad8(int address) { @@ -108,63 +80,6 @@ memory.store8(address, data); } - /** - * Read an ASCIIZ string from the process' memory into a Java String - */ - public String memoryReadString(int address) { - StringBuffer str = new StringBuffer(); - char c; - - while ((c = (char) memoryLoad8(address++)) != 0) - str.append(c); - - return str.toString(); - } - - /** - * Write a Java string (crudely) to an ASCIIZ string in the process' memory - */ - public void memoryWriteString(int byteAddr, String value) { - if (value != null) { - for (int i = 0; i < value.length(); i++) { - memoryStore8(byteAddr + i, (byte) value.charAt(i)); - } - memoryStore8(byteAddr + value.length(), (byte) 0); - } - } - - /** - * Map an anonymous page of memory - * - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable - */ - public int memoryMap(int addr, int len, boolean read, boolean write, - boolean exec) throws MemoryMapException { - return memory.map(addr, len, read, write, exec); - } - - /** - * Simulate an munmap system call. - * - * @param start - * start of memory area to unmap. - * @param length - * length of area. - */ - public int munmap(int start, int length) { - memory.unmap(start, length); - return 0; - } - /* * Utility functions */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-12 09:35:56
|
Revision: 27 http://svn.sourceforge.net/pearcolator/?rev=27&view=rev Author: michael_baer Date: 2007-04-12 02:35:57 -0700 (Thu, 12 Apr 2007) Log Message: ----------- Refactored argument parsing to use the state pattern. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-04-11 21:29:52 UTC (rev 26) +++ src/org/binarytranslator/DBT_Options.java 2007-04-12 09:35:57 UTC (rev 27) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.util.HashMap; +import java.util.Vector; import java.util.Map.Entry; /** @@ -171,7 +172,23 @@ * Read and parse the command line arguments. */ public static void parseArguments(String[] args) { - parseArgumentsToHashmap(args); + + try { + Vector<String> remainingArguments = new Vector<String>(); + ArgumentParser.parse(args, dbtArguments, remainingArguments); + + //did the user give an executable to execute? + if (remainingArguments.size() > 0) { + executableFile = remainingArguments.get(0); + remainingArguments.remove(0); + + executableArguments = new String[remainingArguments.size()]; + remainingArguments.toArray(executableArguments); + } + } + catch (ArgumentParser.ParseException e) { + throw new Error(e.getMessage()); + } for (Entry<String, String> argument : dbtArguments.entrySet()) { String arg = argument.getKey(); @@ -228,67 +245,158 @@ } } - /** - * Takes an array of arguments and parses them as key=value pairs into the hashmap arguments. - */ - private static void parseArgumentsToHashmap(String[] args) { + private static class ArgumentParser { - String key = null; - String value; - int next = 0; + protected State state; + protected final HashMap<String, String> arguments; + protected final Vector<String> remainingArguments; - try { - //are there further arguments? - if (next == args.length) { - return; - } + public static ArgumentParser parse(String[] args, HashMap<String, String> keyValueArguments, Vector<String> remainingArguments) + throws ParseException { - key = args[next++].trim(); + ArgumentParser parser = new ArgumentParser(keyValueArguments, remainingArguments); + parser.parseArguments(args); + return parser; + } + + private ArgumentParser(HashMap<String, String> arguments, Vector<String> remainingArguments) { + this.arguments = arguments; + this.remainingArguments = remainingArguments; + } + + private void parseArguments(String[] args) + throws ParseException { + switchState(new AwaitingKeyState()); - if (!key.startsWith("-")) { - //this is not an argument to the DBT, so it must the file we're trying to execute. - executableFile = key; + int next = 0; + + while (next < args.length) { + String input = args[next++].trim(); - //the remaining arguments may be passed to the executable - executableArguments = new String[args.length - next]; - for (int i = next; i < args.length; i++) - executableArguments[i] = args[next + i]; + int pos = input.indexOf("="); - return; + if (pos == 0) { + //this token has the form "=TEXT" + do { + state.onAssignment(); + input = input.substring(1); + } + while (input.startsWith("=")); + } + else if (pos > 0) { + //the token has the form "TEXT=" + state.onText(input.substring(0, pos)); + state.onAssignment(); + + //handle remaining text (form TEXT=TEXT) + input = input.substring(pos + 1); + } + + if (input.length() > 1) { + state.onText(input); + } } + + state.onEnd(); + } + + protected void switchState(State s) { + state = s; + } + + public static class ParseException extends Exception { + + protected ParseException(String msg) { + super(msg); + } + } + + private interface State { + void onText(String text) throws ParseException; + void onAssignment() throws ParseException; + void onEnd() throws ParseException; + } + + private final class AwaitingKeyState implements State { - //did the user give an argument without spaces in it? - int pos = key.indexOf('='); - if (pos != -1) { - value = key.substring(pos + 1); - key = key.substring(0, pos); + public void onAssignment() throws ParseException { + throw new ParseException("Unexpected token '=' while parsing arguments."); } - else { + + public void onEnd() throws ParseException { + //no further arguments, stop parsing + } + + public void onText(String text) throws ParseException { + switchState(new AwaitingAssignmentState(text)); + } + } + + private final class AwaitingAssignmentState implements State { + + private final String previousInput; + + public AwaitingAssignmentState(String previousInput) { + this.previousInput = previousInput; + } + + public void onAssignment() throws ParseException { + switchState(new ParseValueArgumentState(previousInput)); + } + + public void onEnd() throws ParseException { + //the key has obviously been a single remaining argument + remainingArguments.add(previousInput); + } + + public void onText(String text) throws ParseException { + //the key has obviously been a single remaining argument and now we received the next one + remainingArguments.add(previousInput); + remainingArguments.add(text); - //extract the argument's value - do { - value = args[next++].trim(); - - if (value.startsWith("=")) - { - if (value.length() > 1) - value = value.substring(1); - else - value = ""; - } - } - while ( value.length() == 0 ); + switchState(new ParseRemainingArgumentsState()); } + } + + private final class ParseValueArgumentState implements State { - //store the argument's key and value - if (dbtArguments.containsKey(key)) { - throw new Error(String.format("Parameter %s already defined", key)); + private final String previousInput; + + public ParseValueArgumentState(String previousInput) { + this.previousInput = previousInput; } - - dbtArguments.put(key, value); + + public void onAssignment() throws ParseException { + throw new ParseException("Invalid value for argument '" + previousInput + "'."); + } + + public void onEnd() throws ParseException { + throw new ParseException("Missing value for argument '" + previousInput + "'."); + } + + public void onText(String text) throws ParseException { + if (arguments.containsKey(text)) { + throw new ParseException("Duplicate argument '" + previousInput + "' while parsing arguments."); + } + + arguments.put(previousInput, text); + switchState(new AwaitingKeyState()); + } } - catch (Exception e) { - throw new Error("Invalid argument format for argument " + key); + + private final class ParseRemainingArgumentsState implements State { + + public void onAssignment() throws ParseException { + remainingArguments.add("="); + } + + public void onEnd() throws ParseException { + //no-op + } + + public void onText(String text) throws ParseException { + remainingArguments.add(text); + } } } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-11 21:29:52 UTC (rev 26) +++ src/org/binarytranslator/Main.java 2007-04-12 09:35:57 UTC (rev 27) @@ -47,18 +47,21 @@ */ public static void main(String[] args) { - if (args.length < 1) { - showUsage(); - return; - } - // Process any arguments for the emulator try { DBT_Options.parseArguments(args); } catch (Exception e) { System.err.println("Error while parsing command line arguments."); System.err.println(e.getMessage()); + showUsage(); + return; } + + if (DBT_Options.executableFile == null) { + System.err.println("Missing executable file name"); + showUsage(); + return; + } ProcessSpace ps; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 11:16:14
|
Revision: 37 http://svn.sourceforge.net/pearcolator/?rev=37&view=rev Author: michael_baer Date: 2007-04-13 04:16:14 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Refactored the program main loop into a seperate package (generic.execution) that shall contain all execution strategies. Removed run() method from ProcessSpace. Made GdbStub a seperate execution strategy. Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/execution/ src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/execution/ExecutionController.java src/org/binarytranslator/generic/execution/GdbController.java Removed Paths: ------------- src/org/binarytranslator/generic/gdbstub/ Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/Main.java 2007-04-13 11:16:14 UTC (rev 37) @@ -8,6 +8,9 @@ */ package org.binarytranslator; +import org.binarytranslator.generic.execution.DynamicTranslationController; +import org.binarytranslator.generic.execution.ExecutionController; +import org.binarytranslator.generic.execution.GdbController; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -75,6 +78,21 @@ } report("Sucessfully created process."); - ps.run(); + + if (DBT_Options.debugPS) { + System.out.println("***** INITIAL PROCESS SPACE *****\n"); + System.out.println(ps); + } + + //Create an execution controller and pass execution on to it + ExecutionController controller; + + if (DBT_Options.gdbStub == false) { + controller = new GdbController(DBT_Options.gdbStubPort, ps); + } + else + controller = new DynamicTranslationController(ps); + + controller.run(); } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -3,7 +3,7 @@ import org.binarytranslator.arch.arm.decoder.ARM2IR; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; -import org.binarytranslator.generic.gdbstub.GDBTarget; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.os.loader.Loader; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; @@ -23,7 +23,7 @@ } @Override - public GDBTarget getGDBTarget() { + public GdbTarget getGdbTarget() { throw new UnsupportedOperationException("GDB not implemented."); } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -4,7 +4,7 @@ import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; -import org.binarytranslator.generic.gdbstub.GDBTarget; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -100,8 +100,7 @@ } @Override - public GDBTarget getGDBTarget() { - // TODO Auto-generated method stub + public GdbTarget getGdbTarget() { return null; } Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -14,8 +14,8 @@ import org.binarytranslator.arch.ppc.decoder.PPC2IR; import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.memory.ByteAddressedByteSwapMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -28,7 +28,7 @@ * Capture the running of a PowerPC process */ public abstract class PPC_ProcessSpace extends ProcessSpace implements - GDBTarget { + GdbTarget { /* * Here's what would be in the PowerPC's registers if the binary were running * on a real PowerPC. For speed I am using individual variables, not arrays Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -11,7 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.arch.ppc.os.abi.linux.PPC_LinuxSystemCalls; -import org.binarytranslator.generic.gdbstub.GDBTarget; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.os.abi.linux.LinuxStackInitializer; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; @@ -192,7 +192,7 @@ brk = address; } - public GDBTarget getGDBTarget() { + public GdbTarget getGdbTarget() { return this; } Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -16,8 +16,8 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.generic.os.loader.Loader; @@ -26,7 +26,7 @@ /** * Encapsulate the parts of an X86 process that are common across operating systems */ -public abstract class X86_ProcessSpace extends ProcessSpace implements GDBTarget { +public abstract class X86_ProcessSpace extends ProcessSpace implements GdbTarget { /* * Process defaults @@ -107,7 +107,7 @@ return 8; } - public GDBTarget getGDBTarget() { + public GdbTarget getGdbTarget() { return this; } Added: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java (rev 0) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,38 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.vmInterface.DynamicCodeRunner; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; + +/** + * Runtime loop, goes through the binary and looks in a Hashtable + * to see if we have already translated/compiled this piece of code, if not it + * is compiled. The compiled code is then run. + */ +public class DynamicTranslationController extends ExecutionController { + + public DynamicTranslationController(ProcessSpace ps) { + super(ps); + } + + @Override + public void run() { + // The current block of compiled code. + VM_CodeArray code; + + + try { + // interpretFrom(); // Interpreter - experimental + while (ps.finished == false) { + // Get the compiled code + code = ps.getCodeForPC(ps.getCurrentInstructionAddress()); + // Run the compiled code. + ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps)); + } + } catch (BadInstructionException e) { + System.out.println(e.toString()); + } + } + +} Added: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java (rev 0) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,14 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.os.process.ProcessSpace; + +public abstract class ExecutionController { + + protected final ProcessSpace ps; + + public ExecutionController(ProcessSpace ps) { + this.ps = ps; + } + + public abstract void run(); +} Added: src/org/binarytranslator/generic/execution/GdbController.java =================================================================== --- src/org/binarytranslator/generic/execution/GdbController.java (rev 0) +++ src/org/binarytranslator/generic/execution/GdbController.java 2007-04-13 11:16:14 UTC (rev 37) @@ -0,0 +1,783 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ + +package org.binarytranslator.generic.execution; + +import java.io.*; +import java.net.*; + +import org.binarytranslator.generic.fault.BadInstructionException; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * @author Ian Rogers + * @author Michael Baer + * + * Allows to control the execution of a ProcessSpace by using a remote GDB debugger. + */ +public class GdbController extends + ExecutionController { + + /** An interface that all ProcessSpaces have to implement (at the moment).*/ + public interface GdbTarget { + /** + * Read a register from the target machine. + * + * @param regNum + * A register number, starting from 0. + */ + byte[] readRegisterGDB(int regNum); + + /** + * Run a single instruction + */ + void runOneInstruction() throws BadInstructionException; + + /** + * Has frame base register? + */ + boolean hasFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBFrameBaseRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBStackPointerRegister(); + + /** + * Get the value of the frame base register + */ + int getGDBProgramCountRegister(); + + /** + * Return the address of the current instruction. + */ + int getCurrentInstructionAddress(); + } + + + /** + * The socket that connections will arrive on + */ + private final Socket socket; + + /** + * The stream to read from the socket + */ + private final InputStream in; + + /** + * The stream to read from the socket + */ + private final OutputStream out; + + /** + * A buffer used in the reading/writing of data + */ + private final byte buffer[]; + + /** + * The process being debugged + */ + private final GdbTarget target; + + /** + * Thread to continue or step, a value of -1 means all threads, 0 means any + * thread. + */ + private int threadToStep; + + /** + * Thread to inspect, a value of -1 means all threads, 0 means any thread. + */ + private int threadToInspect; + + /** + * An array of breakpoints + */ + private int breakpoints[]; + + /* GDB Stub commands */ + /** ACK - Acknowledged */ + private final static int ACK = '+'; + + /** NAK - Not acknowledged, implies retransmit */ + private final static int NAK = '-'; + + /** Packet start */ + private final static int START = '$'; + + /** Sequence-ID separator - deprecated */ + private final static int SEQUENCE_ID_SEPERATOR = ':'; + + /** Checksum start */ + private final static int CHECKSUM_START = '#'; + + /** What signal halted the stub? Default is SIGTRAP */ + private final static int LAST_SIGNAL = '?'; + + /** Set thread */ + private final static int SET_THREAD = 'H'; + + /** Stop debugging */ + private final static int KILL_DEBUG = 'k'; + + /** Get memory values */ + private final static int GET_MEM_VALUE = 'm'; + + /** Set memory values */ + private final static int SET_MEM_VALUE = 'M'; + + /** Get a register value */ + private final static int GET_REG_VALUE = 'p'; + + /** Query */ + private final static int QUERY = 'q'; + + /** A verbose packet */ + private final static int VERBOSE_PACKET = 'v'; + + /** Set memory value to binary value */ + private final static int SET_MEM_VALUE_BIN = 'X'; + + /** Remove a breakpoint */ + private final static int REMOVE_BREAKPOINT = 'z'; + + /** Insert a breakpoint */ + private final static int INSERT_BREAKPOINT = 'Z'; + + /* Error codes */ + private final static int CANNOT_ACCESS_MEMORY = 1; + + /** + * Constructor + */ + public GdbController(int port, ProcessSpace ps) { + super(ps); + try { + ServerSocket connectionSocket = new ServerSocket(port); + socket = connectionSocket.accept(); + in = socket.getInputStream(); + out = socket.getOutputStream(); + buffer = new byte[256]; + getACK(); + } catch (IOException e) { + throw new Error("Error opening socket", e); + } + breakpoints = new int[0]; + this.target = ps.getGdbTarget(); + } + + /** + * Main run loop + */ + public void run() { + try { + while (socket.isConnected()) { + int dataEnd = readPacket(); + switch (buffer[1]) { + case GET_REG_VALUE: + handle_getRegValue(dataEnd); + break; + case GET_MEM_VALUE: + handle_getMemValue(dataEnd); + break; + case INSERT_BREAKPOINT: + handle_insertBreakPoint(dataEnd); + break; + case KILL_DEBUG: + System.exit(0); + case LAST_SIGNAL: + handle_lastSignal(dataEnd); + break; + case QUERY: + handle_query(dataEnd); + break; + case REMOVE_BREAKPOINT: + handle_removeBreakPoint(dataEnd); + break; + case SET_MEM_VALUE: + handle_setMemValue(dataEnd); + break; + case SET_MEM_VALUE_BIN: + handle_setMemValueBin(dataEnd); + break; + case SET_THREAD: + handle_setThread(dataEnd); + break; + case VERBOSE_PACKET: + handle_verbose(dataEnd); + break; + default: + throw new Error("Unknown GDB Stub command " + (char) buffer[1]); + } + } + } catch (IOException e) { + throw new Error("Error reading/writing to socket", e); + } + } + + /* Packet commands */ + /** + * Get an acknowledge + */ + private void getACK() throws IOException { + int command = in.read(); + if (command != ACK) { + throw new IOException("Acknowledge expected but got " + (char) command); + } + } + + /** + * Send an acknowledge + */ + private void sendACK() throws IOException { + out.write(ACK); + } + + /** + * Read a packet into the buffer and check the checksum + * + * @return the last byte in the buffer prior to the checksum + */ + private int readPacket() throws IOException { + // Read the packet start + int index = 0; + buffer[index] = (byte) in.read(); + if (buffer[index] != START) { + throw new IOException("Expected the start of a packet ($) but got " + + (char) buffer[index]); + } + // Read the data + int csum = 0; + do { + index++; + buffer[index] = (byte) in.read(); + csum += (int) buffer[index]; + } while (buffer[index] != CHECKSUM_START); + csum -= CHECKSUM_START; + csum &= 0xFF; + // Abort if we got a sequence ID + if (buffer[3] == SEQUENCE_ID_SEPERATOR) { + throw new IOException("Found unsupported sequence ID in packet"); + } + // Read the checksum + index++; + buffer[index] = (byte) in.read(); + index++; + buffer[index] = (byte) in.read(); + int checkSum = (hexToInt(buffer[index - 1]) << 4) | hexToInt(buffer[index]); + if (checkSum == csum) { + report("Read: " + bufferToString(0, index)); + sendACK(); + return index - 3; + } else { + throw new IOException("Packet's checksum of " + checkSum + + " doesn't match computed checksum of " + csum); + } + } + + /** + * Send the command + */ + private void sendCommand(byte command[]) throws IOException { + buffer[0] = START; + int index = 1; + int csum = 0; + if (command != null) { + for (int i = 0; i < command.length; i++, index++) { + buffer[index] = command[i]; + csum += command[i]; + } + } + buffer[index] = CHECKSUM_START; + index++; + buffer[index] = intToHex(csum >> 4); + index++; + buffer[index] = intToHex(csum); + out.write(buffer, 0, index + 1); + report("Sent: " + bufferToString(0, index)); + getACK(); + } + + /** + * Send a reply of 'OK' + */ + private void replyOK() throws IOException { + byte command[] = { 'O', 'K' }; + sendCommand(command); + } + + /** + * Send a message saying that a sig trap stopped us + */ + private void sendStoppedByTrap() throws IOException { + // report that a SIGTRAP halted the debugger + // byte command[] = {'S','0','5'}; <- a command to just say stopped by + // SIGTRAP + byte command[]; + int index; + if (target.hasFrameBaseRegister()) { + // Add base pointer to packet + command = new byte[39]; + int bpReg = target.getGDBFrameBaseRegister(); + command[3] = intToHex(bpReg >> 4); + command[4] = intToHex(bpReg); + command[5] = ':'; + byte bpVal[] = target.readRegisterGDB(bpReg); + command[6] = intToHex(bpVal[0] >> 4); + command[7] = intToHex(bpVal[0]); + command[8] = intToHex(bpVal[1] >> 4); + command[9] = intToHex(bpVal[1]); + command[10] = intToHex(bpVal[2] >> 4); + command[11] = intToHex(bpVal[2]); + command[12] = intToHex(bpVal[3] >> 4); + command[13] = intToHex(bpVal[3]); + command[14] = ';'; + index = 15; + } else { + command = new byte[27]; + index = 3; + } + command[0] = 'T'; + command[1] = '0'; + command[2] = '5'; // stopped by trap + { // Add stack pointer to packet + int spReg = target.getGDBStackPointerRegister(); + command[index] = intToHex(spReg >> 4); + index++; + command[index] = intToHex(spReg); + index++; + command[index] = ':'; + index++; + byte spVal[] = target.readRegisterGDB(spReg); + command[index] = intToHex(spVal[0] >> 4); + index++; + command[index] = intToHex(spVal[0]); + index++; + command[index] = intToHex(spVal[1] >> 4); + index++; + command[index] = intToHex(spVal[1]); + index++; + command[index] = intToHex(spVal[2] >> 4); + index++; + command[index] = intToHex(spVal[2]); + index++; + command[index] = intToHex(spVal[3] >> 4); + index++; + command[index] = intToHex(spVal[3]); + index++; + command[index] = ';'; + index++; + } + { // Add program counter to packet + int pcReg = target.getGDBProgramCountRegister(); + command[index] = intToHex(pcReg >> 4); + index++; + command[index] = intToHex(pcReg); + index++; + command[index] = ':'; + index++; + byte pcVal[] = target.readRegisterGDB(pcReg); + command[index] = intToHex(pcVal[0] >> 4); + index++; + command[index] = intToHex(pcVal[0]); + index++; + command[index] = intToHex(pcVal[1] >> 4); + index++; + command[index] = intToHex(pcVal[1]); + index++; + command[index] = intToHex(pcVal[2] >> 4); + index++; + command[index] = intToHex(pcVal[2]); + index++; + command[index] = intToHex(pcVal[3] >> 4); + index++; + command[index] = intToHex(pcVal[3]); + index++; + command[index] = ';'; + index++; + } + sendCommand(command); + } + + /** + * Send a reply of 'ENN' indicating an error with error code NN + */ + private void replyError(int nn) throws IOException { + byte command[] = { 'E', intToHex(nn >> 4), intToHex(nn) }; + sendCommand(command); + } + + /** + * A command arrived to set the thread for subsequent operations + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setThread(int dataEnd) throws IOException { + if (buffer[2] == 'c') { + threadToStep = Integer.parseInt(bufferToString(3, dataEnd)); + replyOK(); + } else if (buffer[2] == 'g') { + threadToInspect = Integer.parseInt(bufferToString(3, dataEnd)); + replyOK(); + } else { + replyError(0); + } + } + + /** + * A query packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_query(int dataEnd) throws IOException { + if (buffer[2] == 'C') { // query current thread + // send reply that current thread is 1 + byte command[] = { 'Q', 'C', '0', '1' }; + sendCommand(command); + } else if (doesBufferMatch(2, new byte[] { 'O', 'f', 'f', 's', 'e', 't', + 's' })) { + // query relocation offsets. As the binary is loaded where it + // hoped then we don't specify any relocation offsets. + byte command[] = { 'T', 'e', 'x', 't', '=', '0', ';', 'D', 'a', 't', 'a', + '=', '0', ';', 'B', 's', 's', '=', '0' }; + sendCommand(command); + } else if (doesBufferMatch(2, new byte[] { 'S', 'y', 'm', 'b', 'o', 'l', + ':', ':' })) { + // GDB is telling us it will handle symbol queries for us - nice :-) + replyOK(); + } else { + // unrecognized query + sendCommand(null); + } + } + + /** + * A last signal packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_lastSignal(int dataEnd) throws IOException { + sendStoppedByTrap(); + } + + /** + * A get register value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_getRegValue(int dataEnd) throws IOException { + int regNum; + if (buffer[3] != CHECKSUM_START) { + regNum = (hexToInt(buffer[2]) << 4) | hexToInt(buffer[3]); + } else { + regNum = hexToInt(buffer[2]); + } + byte value[] = target.readRegisterGDB(regNum); + byte hexValue[] = new byte[value.length * 2]; + for (int i = 0; i < value.length; i++) { + hexValue[i * 2] = intToHex(value[i] >> 4); + hexValue[(i * 2) + 1] = intToHex(value[i]); + } + sendCommand(hexValue); + } + + /** + * A get memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_getMemValue(int dataEnd) throws IOException { + String data = bufferToString(2, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int count = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + try { + byte value[] = new byte[count * 2]; + for (int i = 0; i < count; i++) { + byte byteVal = (byte) ps.memory.loadUnsigned8(address + i); + value[i * 2] = intToHex(byteVal >> 4); + value[(i * 2) + 1] = intToHex(byteVal); + } + sendCommand(value); + } catch (NullPointerException e) { + replyError(CANNOT_ACCESS_MEMORY); + } + } + + /** + * A set memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setMemValue(int dataEnd) throws IOException { + int address = readHexValFromBuffer(2); + int count = readHexValFromBuffer(indexOf(2, ',') + 1); + int start = indexOf(2, ':') + 1; + try { + byte value[] = new byte[2]; + for (int i = 0; i < count; i++) { + byte byteVal = (byte) ((hexToInt(buffer[start + (i * 2)]) << 4) | (hexToInt(buffer[start + + (i * 2) + 1]))); + ps.memory.store8(address + i, byteVal); + } + replyOK(); + } catch (NullPointerException e) { + replyError(CANNOT_ACCESS_MEMORY); + } + } + + /** + * A set memory value packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_setMemValueBin(int dataEnd) throws IOException { + // Report not supported + sendCommand(null); + } + + /** + * A verbose packet arrived + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_verbose(int dataEnd) throws IOException { + if (doesBufferMatch(2, new byte[] { 'C', 'o', 'n', 't' })) { + if (buffer[6] == '?') { // query what verbose resume commands are + // supported + byte command[] = { 'v', 'C', 'o', 'n', 't', ';', 's', ';', 'S', ';', + 'c', ';', 'C' }; + sendCommand(command); + } else { // a verbose resume packet + int index = 6; + while (index < dataEnd) { + if (buffer[index] != ';') { + // values for each thread should be ';' separated + replyError(0); + break; + } else { + switch (buffer[index + 1]) { + case 's': + // the next two optional characters specify the thread + // to step, we have one thread so we ignore them + try { + target.runOneInstruction(); + index = dataEnd; + // report that a SIGTRAP halted the debugger + sendStoppedByTrap(); + } catch (BadInstructionException e) { + // report that a SIGILL halted the debugger + byte command[] = { 'S', '0', '4' }; + sendCommand(command); + } + break; + case 'c': + // the next two optional characters specify the thread + // to step, we have one thread so we ignore them + try { + boolean hitBreakpoint; + do { + target.runOneInstruction(); + hitBreakpoint = false; + int pc = target.getCurrentInstructionAddress(); + for (int i = 0; i < breakpoints.length; i++) { + if (pc == breakpoints[i]) { + hitBreakpoint = true; + break; + } + } + } while (!hitBreakpoint); + index = dataEnd; + // report that a SIGTRAP halted the debugger + sendStoppedByTrap(); + } catch (BadInstructionException e) { + // report that a SIGILL halted the debugger + byte command[] = { 'S', '0', '4' }; + sendCommand(command); + } + break; + case 'S': + case 'C': + default: + replyError(0); + break; + } + } + } + } + } else { // unknown verbose packet + replyError(0); + } + } + + /** + * Insert a break point + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_insertBreakPoint(int dataEnd) throws IOException { + String data = bufferToString(4, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int length = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + switch (buffer[2]) { // determine the breakpoint type + case '0': // memory break point + int newbp[] = new int[breakpoints.length + 1]; + System.arraycopy(breakpoints, 0, newbp, 0, breakpoints.length); + newbp[breakpoints.length] = address; + breakpoints = newbp; + replyOK(); + break; + default: // unrecognized breakpoint type + sendCommand(null); + } + } + + /** + * Remove a break point + * + * @param dataEnd + * the last character in the buffer prior to the checksum + */ + private void handle_removeBreakPoint(int dataEnd) throws IOException { + String data = bufferToString(4, dataEnd); + int address = Integer.parseInt(data.substring(0, data.indexOf(',')), 16); + int length = Integer.parseInt(data.substring(data.indexOf(',') + 1), 16); + switch (buffer[2]) { // determine the breakpoint type + case '0': // memory break point + int breakpointToRemove = -1; + for (int i = 0; i < breakpoints.length; i++) { + if (breakpoints[i] == address) { + breakpointToRemove = i; + break; + } + } + if (breakpointToRemove >= 0) { + int newbp[] = new int[breakpoints.length - 1]; + for (int fromIndex = 0, toIndex = 0; fromIndex < breakpoints.length; fromIndex++) { + if (fromIndex != breakpointToRemove) { + newbp[toIndex] = breakpoints[fromIndex]; + toIndex++; + } + } + breakpoints = newbp; + replyOK(); + } else { // breakpoint wasn't found + sendCommand(null); + } + break; + default: // unrecognized breakpoint type + sendCommand(null); + } + } + + /* Utilities */ + /** + * Convert the ASCII character in the byte, convert it to its integer value + */ + private static int hexToInt(byte val) { + if ((val >= 'a') && (val <= 'f')) { + return val - 'a' + 10; + } else if ((val >= 'A') && (val <= 'F')) { + return val - 'A' + 10; + } else if ((val >= '0') && (val <= '9')) { + return val - '0'; + } else { // found none hex value + return -1; + } + } + + /** + * Convert the nibble integer into the ASCII character + */ + private static byte intToHex(int val) { + val &= 0xF; + if ((val >= 0) && (val <= 9)) { + return (byte) (val + '0'); + } else { // ((val >= 10) && (val <= 15)) + return (byte) (val + 'a' - 10); + } + } + + /** + * Convert a range in the buffer into a String + */ + private String bufferToString(int start, int end) { + StringBuffer sb = new StringBuffer(end - start + 1); + for (; start <= end; start++) { + sb.append((char) buffer[start]); + } + return sb.toString(); + } + + /** + * Read a hexadecimal value from the buffer + */ + private int readHexValFromBuffer(int start) throws IOException { + int result = 0; + for (int i = 0; i < 8; i++) { + int hexVal = hexToInt(buffer[start + i]); + if (hexVal == -1) + break; + result <<= 4; + result |= hexVal; + } + return result; + } + + /** + * Does the buffer starting at start match the byte array match + */ + private boolean doesBufferMatch(int start, byte match[]) { + for (int i = 0; i < match.length; i++) { + if (buffer[start + i] != match[i]) { + return false; + } + } + return true; + } + + /** + * Return the first index of the specified character + */ + private int indexOf(int start, char toFind) { + for (int i = start; i < buffer.length; i++) { + if (buffer[i] == (byte) toFind) { + return i; + } + } + return -1; + } + + /** + * Debug information + * + * @param s + * string of debug information + */ + private static void report(String s) { + if (true) { + System.out.print("GDBStub:"); + System.out.println(s); + } + } +} Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-13 11:16:14 UTC (rev 37) @@ -8,27 +8,24 @@ */ package org.binarytranslator.generic.os.process; +import java.io.IOException; +import java.io.RandomAccessFile; import java.util.Hashtable; -import java.io.*; -import org.jikesrvm.compilers.common.VM_CompiledMethod; -import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; - -import org.binarytranslator.vmInterface.DBT_Trace; -import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; +import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.generic.branch.BranchLogic; +import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.gdbstub.GDBStub; -import org.binarytranslator.generic.gdbstub.GDBTarget; import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; -import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; -import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; +import org.binarytranslator.vmInterface.DBT_Trace; +import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; +import org.jikesrvm.compilers.common.VM_CompiledMethod; +import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; @@ -289,43 +286,6 @@ } /** - * Runtime loop, goes through the binary and looks in the Hashtable codeHash - * to see if we have already translated/compiled this piece of code, if not it - * is compiled. The compiled code is then run. - */ - public void run() { - if (DBT_Options.debugRuntime) { - System.out.println("Main: run"); - } - - // The current block of compiled code. - VM_CodeArray code; - - if (DBT_Options.debugPS) { - System.out.println("***** INITIAL PROCESS SPACE *****\n" + this); - System.out.println(this); - // dumpStack(20); - } - - if (DBT_Options.gdbStub == false) { - try { - // interpretFrom(); // Interpreter - experimental - while (finished == false) { - // Get the compiled code - code = getCodeForPC(getCurrentInstructionAddress()); - // Run the compiled code. - setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, this)); - } - } catch (BadInstructionException e) { - System.out.println(e.toString()); - } - } else { - GDBStub gdbStub = new GDBStub(DBT_Options.gdbStubPort, this); - gdbStub.run(); - } - } - - /** * Entry point for system calls */ public abstract void doSysCall(); @@ -383,5 +343,5 @@ /** * Return an interface that allows GDB to read from this process */ - public abstract GDBTarget getGDBTarget(); + public abstract GdbTarget getGdbTarget(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-14 11:35:55
|
Revision: 53 http://svn.sourceforge.net/pearcolator/?rev=53&view=rev Author: captain5050 Date: 2007-04-14 04:35:53 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Clear up compiler warnings running current test code Modified Paths: -------------- src/org/binarytranslator/DBT.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/DBT.java =================================================================== --- src/org/binarytranslator/DBT.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/DBT.java 2007-04-14 11:35:53 UTC (rev 53) @@ -1,33 +1,60 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright The University of Manchester 2003-2007 + */ package org.binarytranslator; import org.jikesrvm.VM; +import org.vmmagic.pragma.Uninterruptible; +/** + * Common utility routines for the running DBT. Generally this class is dressing + * up methods from org.jikesrvm.VM. + */ public final class DBT { - public static final boolean VerifyAssertions = true; - + /** Should the following assertion be checked? */ + public static final boolean VerifyAssertions = VM.VerifyAssertions; + + /** + * Assert the following condition is true, if false then fail with stack trace + * @param cond the condition that should be true + */ public static void _assert(boolean cond) { - - if (!VerifyAssertions) - return; - - if (VM.VerifyAssertions) + if (!VerifyAssertions) { + // Checking an assertion in a production build is a bad idea + fail("Assertion checked when assertions should be disabled.\n" + + "Please guard the assertion with DBT.VerifyAssertions"); + } else { VM._assert(cond); - else - { - if (!cond) { - //assertion failed, see if we can get some info on where the assertion occurred - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - - if (trace.length > 0) { - StackTraceElement source = trace[trace.length-1]; - System.err.println("Assertion failed in: " + source.getFileName() + "(" + source.getLineNumber() + ")"); - } - else { - System.err.println("Assertion failed. No stack trace on assertion source available."); - } - - System.exit(-1); - } } } + + /** + * Exit and print stack trace + * @param message failure message + */ + @Uninterruptible + public static void fail(String message) { + VM.sysFail(message); + } + + /** + * Write the given message + */ + @Uninterruptible + public static void write(String message) { + VM.write(message); + } + + /** + * Write the given int + */ + @Uninterruptible + public static void write(int message) { + VM.write(message); + } } Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-14 11:35:53 UTC (rev 53) @@ -18,6 +18,7 @@ import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; +import org.vmmagic.pragma.Uninterruptible; /** * CallBasedMemory abstraction: @@ -415,6 +416,7 @@ * @param callAddress * the address associated with this call */ + @Uninterruptible public VM_MethodReference getMethodRef(int callAddress) { switch (callAddress) { case DBT_Trace.MEMORY_STORE8: Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-14 11:35:53 UTC (rev 53) @@ -12,6 +12,7 @@ import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; import org.jikesrvm.classloader.VM_MethodReference; import org.binarytranslator.vmInterface.TranslationHelper; +import org.vmmagic.pragma.Uninterruptible; import java.io.RandomAccessFile; /** @@ -291,6 +292,7 @@ * @param callAddress * the address associated with this call */ + @Uninterruptible public VM_MethodReference getMethodRef(int callAddress) { throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-14 11:35:53 UTC (rev 53) @@ -11,6 +11,7 @@ import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DummyDynamicCodeRunner; +import org.binarytranslator.DBT; import org.jikesrvm.compilers.common.VM_CompiledMethod; import org.jikesrvm.compilers.common.VM_CompiledMethods; import org.jikesrvm.classloader.VM_NormalMethod; @@ -230,7 +231,8 @@ .asMethodReference(), JBC_invokevirtual); break; case BAD_INSTRUCTION_NEW: - throw new Error("Todo: dynamic linking for new bad instruction exception"); + DBT.fail("Todo: dynamic linking for new bad instruction exception"); + break; case BAD_INSTRUCTION_INIT: dynamicLink.set(DecoderUtils.badInstrKlassInitMethod.getMemberRef() .asMethodReference(), JBC_invokevirtual); @@ -246,9 +248,8 @@ dynamicLink.set(ps.memory.getMethodRef(bcIndex), JBC_invokevirtual); break; default: - throw new Error( - "Trying to dynamic link inside a DBT trace for an unknown dynamic link location: 0x" - + Integer.toHexString(bcIndex)); + DBT.write(bcIndex); + DBT.fail("Trying to dynamic link inside a DBT trace for an unknown dynamic link location"); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-18 17:40:18
|
Revision: 69 http://svn.sourceforge.net/pearcolator/?rev=69&view=rev Author: michael_baer Date: 2007-04-18 10:40:18 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Intermediate commit: First version of an ARM interpreter that is able to run a small loop. Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/DebugMemory.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/Main.java 2007-04-18 17:40:18 UTC (rev 69) @@ -8,9 +8,12 @@ */ package org.binarytranslator; +import java.io.File; + import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; +import org.binarytranslator.generic.execution.InterpreterController; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -60,11 +63,18 @@ return; } + //check if the user actually supplied an executable name if (DBT_Options.executableFile == null) { System.err.println("Missing executable file name"); showUsage(); return; } + + //also make sure that the said executable really exists + if (!new File(DBT_Options.executableFile).exists()) { + System.err.println("The specified executable '" + DBT_Options.executableFile + "' could not be found."); + return; + } ProcessSpace ps; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 17:40:18 UTC (rev 69) @@ -7,7 +7,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataProcessing; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataTransfer; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorRegisterTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CountLeadingZeros; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.IntMultiply; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.LongMultiply; @@ -143,7 +142,10 @@ * @return A human readable form of this instructions condition. */ private String cond(Instruction instr) { - return instr.getCondition().name(); + if (instr.getCondition() == Condition.AL) + return ""; + else + return instr.getCondition().name(); } /** @@ -157,7 +159,7 @@ private final String operand(OperandWrapper op) { switch (op.getType()) { case Immediate: - return String.format("#%x", op.getImmediate()); + return String.format("#%d", op.getImmediate()); case ImmediateShiftedRegister: return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), @@ -165,9 +167,9 @@ case PcRelative: if (address != -1) - return String.format("#%x", op.getOffset() + address + 8); + return String.format("#0x%x", op.getOffset() + address + 8); else - return String.format("#<%x + pc>", op.getOffset()); + return String.format("#<%d + pc>", op.getOffset()); case Register: return "r" + op.getRegister(); @@ -193,14 +195,15 @@ // Filter instructions that only take one parameter if (instr.getOpcode() != DataProcessing.Opcode.MOV - && instr.getOpcode() != DataProcessing.Opcode.MVN) { + && instr.getOpcode() != DataProcessing.Opcode.MVN + && instr.getOpcode() != DataProcessing.Opcode.CLZ) { optionalParam = ", " + operand(instr.getOperand2()); } else optionalParam = ""; - setResult(String.format("%s r%d, r%d %s", mnemonic, instr.getRd(), instr - .getRn(), optionalParam)); + setResult(String.format("%s r%d, r%d%s", mnemonic, instr.getRd(), instr + .getOperandRegister(), optionalParam)); } public void visit(SingleDataTransfer instr) { @@ -308,7 +311,7 @@ public void visit(SoftwareInterrupt instr) { - setResult(String.format("SWI%s #%x", cond(instr), instr + setResult(String.format("SWI%s #0x%x", cond(instr), instr .getInterruptNumber())); } @@ -317,15 +320,15 @@ String mnemonic = instr.link() ? "BL" : "B"; if (address != -1) - setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr.getOffset() + address + 8)); + setResult(String.format("%s%s #%d", mnemonic, cond(instr), instr.getOffset() + address + 8)); else - setResult(String.format("%s%s #<%x + pc>", mnemonic, cond(instr), instr.getOffset())); + setResult(String.format("%s%s #<%d + pc>", mnemonic, cond(instr), instr.getOffset())); } public void visit(BranchExchange instr) { String mnemonic = instr.link ? "BLX" : "BX"; - setResult(String.format("%s%s #%x", mnemonic, cond(instr), operand(instr + setResult(String.format("%s%s #%d", mnemonic, cond(instr), operand(instr .target()))); } @@ -407,11 +410,5 @@ setResult(String.format("MSR%s %s, %s", cond(instr), fields, operand(instr.getSource()))); } - - public void visit(CountLeadingZeros instr) { - - setResult(String.format("CLZ%s r%s r%s ", cond(instr), instr.getRd(), - instr.getRm())); - } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-18 17:40:18 UTC (rev 69) @@ -180,7 +180,7 @@ //bit 6 and 7 are clear if (Utils.getBit(instr, 4)) { if (Utils.getBit(instr, 22)) - return factory.createCountLeadingZeros(instr); + return factory.createDataProcessing(instr); //should be a CLZ instruction else return factory.createBranchExchange(instr); } @@ -249,7 +249,6 @@ T createCoprocessorRegisterTransfer(int instr); T createMoveFromStatusRegister(int instr); T createMoveToStatusRegister(int instr); - T createCountLeadingZeros(int instr); T createUndefinedInstruction(int instr); } @@ -283,10 +282,6 @@ return new CoprocessorRegisterTransfer(instr); } - public Instruction createCountLeadingZeros(int instr) { - return new CountLeadingZeros(instr); - } - public Instruction createDataProcessing(int instr) { return new DataProcessing(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-18 17:40:18 UTC (rev 69) @@ -19,5 +19,4 @@ void visit(CoprocessorRegisterTransfer instr); void visit(MoveFromStatusRegister instr); void visit(MoveToStatusRegister instr); - void visit(CountLeadingZeros instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 17:40:18 UTC (rev 69) @@ -28,7 +28,7 @@ protected final Condition condition; private Instruction(int instr) { - condition = Condition.values()[(byte) Utils.getBits(instr, 28, 31)]; + condition = Condition.values()[(instr & 0xF0000000) >>> 28]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ @@ -190,6 +190,22 @@ return new PcRelativeOperand(offset); } + public static OperandWrapper decodeDataProcessingOperand(int instr) { + if (Utils.getBit(instr, 25)) { + //this is a right-rotated immediate value + byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) << 2); + int value = instr & 0xFF; + + if (shiftAmount == 0) + return new ImmediateOperand(value); + else + return new RightRotatedImmediateOperand(value, shiftAmount); + } + else { + return decodeShiftedRegister(instr); + } + } + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { ShiftType shift = ShiftType.values()[Utils.getBits(instr, 5, 6)]; @@ -283,6 +299,39 @@ } } + /** Represents an immediate value operand. */ + protected static class RightRotatedImmediateOperand extends ImmediateOperand { + + /** @see #getShiftAmount() */ + protected final byte shiftAmount; + + protected RightRotatedImmediateOperand(int immediate, byte shiftAmount) { + super(Integer.rotateRight(immediate, shiftAmount)); + this.shiftAmount = shiftAmount; + } + + @Override + public int getImmediate() { + return immediate; + } + + /** The amount of shifting that had to be performed to create this immediate. */ + @Override + public byte getShiftAmount() { + return shiftAmount; + } + + @Override + public ShiftType getShiftType() { + return ShiftType.ROR; + } + + @Override + public Type getType() { + return Type.Immediate; + } + } + protected static class PcRelativeOperand extends OperandWrapper { protected final int offset; @@ -392,14 +441,13 @@ } /** Represents a Data Processing instruction. */ - public static class DataProcessing extends - TwoRegistersTemplate { + public static class DataProcessing extends Instruction { /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing * instruction. */ public enum Opcode { - AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN + AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, CLZ } /** @see #hasSetConditionCodes() */ @@ -411,18 +459,42 @@ /** @see #getOperand2() */ protected final OperandWrapper operand2; + /** @see #getOperandRegister() */ + protected final byte operandRegister; + + /** @see #getRd() */ + protected final byte Rd; + public DataProcessing(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); updateConditionCodes = Utils.getBit(instr, 20); - opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; - - if (Utils.getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate(Integer.rotateRight(instr & 0xFF, Utils.getBits(instr, 8, 11) << 2)); - else - operand2 = OperandWrapper.decodeShiftedRegister(instr); + + if (Utils.getBits(instr, 20, 27) == 0x16 && Utils.getBits(instr, 4, 7) == 1) { + //this is a CLZ instruction, which we're catching and merging into the data processing instructions + operandRegister = (byte) (instr & 0xF); + opcode = Opcode.CLZ; + operand2 = OperandWrapper.createImmediate(0); + } + else { + operandRegister = (byte) Utils.getBits(instr, 16, 19); + opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; + operand2 = OperandWrapper.decodeDataProcessingOperand(instr); + } } + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getOperandRegister() { + return operandRegister; + } + /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ public final Opcode getOpcode() { return opcode; @@ -498,9 +570,9 @@ size = TransferSize.Word; if (Utils.getBit(instr, 25)) - offset = OperandWrapper.createImmediate(instr & 0xFF); + offset = OperandWrapper.decodeShiftedRegister(instr); else - offset = OperandWrapper.decodeShiftedRegister(instr); + offset = OperandWrapper.createImmediate(instr & 0xFFF); } else { //this is a byte or half-word transfer @@ -524,6 +596,9 @@ //The decoder should make sure that we're never being called with this combination if (DBT.VerifyAssertions) DBT._assert(!signExtend || isLoad); } + + //this instruction variant yields an undefined result + if (DBT.VerifyAssertions) DBT._assert(Rd != 15 || !writeBack); } /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ @@ -760,7 +835,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = instr & 0xFFF; + offset = Utils.signExtend((instr & 0xFFF) << 2, 14); } /** Should the current PC be put into the lr? */ @@ -1082,13 +1157,9 @@ transferExtension = Utils.getBit(instr, 17); transferStatus = Utils.getBit(instr, 18); transferFlags = Utils.getBit(instr, 19); - transferSavedPSR = Utils.getBit(instr, 22); - if (Utils.getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << Utils.getBits(instr, 8, 11)); - else - sourceOperand = OperandWrapper.decodeShiftedRegister(instr); + sourceOperand = OperandWrapper.decodeDataProcessingOperand(instr); } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ @@ -1126,36 +1197,4 @@ visitor.visit(this); } } - - /** Represents a CLZ instruction. */ - public static class CountLeadingZeros extends Instruction { - - /** @see #getRm() */ - protected final byte Rm; - - /** @see #getRd() */ - protected final byte Rd; - - public CountLeadingZeros(int instr) { - super(instr); - - Rm = (byte) (instr & 0xF); - Rd = (byte) Utils.getBits(instr, 12, 15); - } - - /** Returns the source register for this operation. */ - public final byte getRm() { - return Rm; - } - - /** Returns the destination register for this operation. */ - public final byte getRd() { - return Rd; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 17:40:18 UTC (rev 69) @@ -1,43 +1,116 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.generic.decoder.Interpreter; -import org.binarytranslator.generic.decoder.Interpreter.Instruction; -public class ARM_Interpreter { +public class ARM_Interpreter implements Interpreter { protected final ARM_ProcessSpace ps; - protected final ARM_Registers regs; + protected final InterpreterFactory instructionFactory; public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; this.regs = ps.registers; + instructionFactory = new InterpreterFactory(); } + public Instruction decode(int pc) { + + int binaryInstruction = ps.memory.loadInstruction32(pc); + ARM_Instruction instruction = ARM_InstructionDecoder.decode(binaryInstruction, instructionFactory); + + if (instruction.getCondition() != Condition.AL) { + return new ConditionalDecorator(instruction); + } + + return instruction; + } + + private interface ARM_Instruction extends Interpreter.Instruction { + Condition getCondition(); + } + private final class ConditionalDecorator implements Interpreter.Instruction { - protected final Interpreter.Instruction conditionalInstruction; + protected final ARM_Instruction conditionalInstruction; - protected ConditionalDecorator(Interpreter.Instruction i) { + protected ConditionalDecorator(ARM_Instruction i) { conditionalInstruction = i; } - + public void execute() { - conditionalInstruction.execute(); + if (isConditionTrue()) + conditionalInstruction.execute(); } public int getSuccessor(int pc) { return -1; } + + private boolean isConditionTrue() { + switch (conditionalInstruction.getCondition()) { + case AL: + return true; + + case CC: + return !regs.isCarrySet(); + + case CS: + return regs.isCarrySet(); + + case EQ: + return regs.isZeroSet(); + + case GE: + return regs.isNegativeSet() == regs.isOverflowSet(); + + case GT: + return (regs.isNegativeSet() == regs.isOverflowSet()) && regs.isZeroSet(); + + case HI: + return regs.isCarrySet() && !regs.isZeroSet(); + + case LE: + return regs.isZeroSet() || (regs.isNegativeSet() == regs.isOverflowSet()); + + case LS: + return !regs.isCarrySet() || regs.isZeroSet(); + + case LT: + return regs.isNegativeSet() != regs.isOverflowSet(); + + case MI: + return regs.isNegativeSet(); + + case NE: + return !regs.isZeroSet(); + + case NV: + return false; + + case PL: + return !regs.isNegativeSet(); + + case VC: + return !regs.isOverflowSet(); + + case VS: + return regs.isOverflowSet(); + + default: + throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + } + } } private abstract class DataProcessing extends ARM_Instructions.DataProcessing - implements Interpreter.Instruction { + implements ARM_Instruction { protected boolean shifterCarryOut; @@ -59,43 +132,59 @@ switch (operand.getShiftType()) { case ASR: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount >= 32) { + shifterCarryOut = Utils.getBit(value, 31); + return shifterCarryOut ? 0xFFFFFFFF : 0; + } if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >>> shiftAmount; } + + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; case LSL: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); - return value << shiftAmount; } + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + case LSR: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >> shiftAmount; } + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + case ROR: if (shiftAmount == 0) { @@ -120,6 +209,15 @@ } } + protected int resolveOperand1() { + + if (operandRegister == ARM_Registers.PC) { + return regs.get(operandRegister) + 8; + } + + return regs.get(operandRegister); + } + protected int resolveOperand2() { int value; @@ -131,6 +229,8 @@ shifterCarryOut = regs.isCarrySet(); else shifterCarryOut = (value & 0x80000000) != 0; + + return value; case Register: shifterCarryOut = regs.isCarrySet(); @@ -147,7 +247,6 @@ } } - public abstract void execute(); protected final void setFlagsForResult(int result) { @@ -160,7 +259,7 @@ } } } - + protected final void setFlagsForAdd(int lhs, int rhs) { if (updateConditionCodes) { @@ -177,7 +276,7 @@ } public int getSuccessor(int pc) { - if (Rd == 15) + if (Rd != 15) return pc + 4; else return -1; @@ -189,11 +288,10 @@ protected DataProcessing_And(int instr) { super(instr); } - @Override public void execute() { - int result = regs.get(Rn) & resolveOperand2(); + int result = resolveOperand1() & resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } @@ -207,7 +305,7 @@ @Override public void execute() { - int result = regs.get(Rn) ^ resolveOperand2(); + int result = resolveOperand1() ^ resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } @@ -218,16 +316,12 @@ public DataProcessing_Add(int instr) { super(instr); } - - protected int resolveOperand1() { - return regs.get(Rn); - } - + public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); int result = operand1 + operand2; - + regs.set(Rd, result); setFlagsForAdd(operand1, operand2); } @@ -260,6 +354,7 @@ private class DataProcessing_Adc extends DataProcessing_Add { protected int cachedOperand1; + protected int cachedOperand2; protected DataProcessing_Adc(int instr) { @@ -307,7 +402,7 @@ return -cachedOperand2; } } - + private class DataProcessing_Rsc extends DataProcessing_Adc { protected DataProcessing_Rsc(int instr) { @@ -319,7 +414,7 @@ return -cachedOperand1; } } - + private class DataProcessing_Tst extends DataProcessing { protected DataProcessing_Tst(int instr) { @@ -328,10 +423,10 @@ @Override public void execute() { - setFlagsForResult(regs.get(Rn) & resolveOperand2()); + setFlagsForResult(resolveOperand1() & resolveOperand2()); } } - + private class DataProcessing_Teq extends DataProcessing { protected DataProcessing_Teq(int instr) { @@ -340,10 +435,10 @@ @Override public void execute() { - setFlagsForResult(regs.get(Rn) ^ resolveOperand2()); + setFlagsForResult(resolveOperand1() ^ resolveOperand2()); } } - + private class DataProcessing_Cmp extends DataProcessing { protected DataProcessing_Cmp(int instr) { @@ -352,10 +447,10 @@ @Override public void execute() { - setFlagsForAdd(regs.get(Rn), -resolveOperand2()); + setFlagsForAdd(resolveOperand1(), -resolveOperand2()); } } - + private class DataProcessing_Cmn extends DataProcessing { protected DataProcessing_Cmn(int instr) { @@ -364,10 +459,10 @@ @Override public void execute() { - setFlagsForAdd(regs.get(Rn), resolveOperand2()); + setFlagsForAdd(resolveOperand1(), resolveOperand2()); } } - + private class DataProcessing_Orr extends DataProcessing { protected DataProcessing_Orr(int instr) { @@ -376,12 +471,12 @@ @Override public void execute() { - int result = regs.get(Rn) | resolveOperand2(); + int result = resolveOperand1() | resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } } - + private class DataProcessing_Mov extends DataProcessing { protected DataProcessing_Mov(int instr) { @@ -395,7 +490,7 @@ setFlagsForResult(result); } } - + private class DataProcessing_Bic extends DataProcessing { protected DataProcessing_Bic(int instr) { @@ -404,12 +499,12 @@ @Override public void execute() { - int result = regs.get(Rn) & (~resolveOperand2()); + int result = resolveOperand1() & (~resolveOperand2()); regs.set(Rd, result); setFlagsForResult(result); } } - + private class DataProcessing_Mvn extends DataProcessing { protected DataProcessing_Mvn(int instr) { @@ -424,125 +519,175 @@ } } - private class Swap extends ARM_Instructions.Swap implements Interpreter.Instruction { + private class DataProcessing_Clz extends DataProcessing { + protected DataProcessing_Clz(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = Integer.numberOfLeadingZeros(resolveOperand1()); + regs.set(Rd, result); + } + } + + private class Swap extends ARM_Instructions.Swap implements + ARM_Instruction { + public Swap(int instr) { super(instr); } public void execute() { int memAddr = regs.get(Rn); - + //swap exchanges the value of a memory address with the value in a register int tmp = ps.memory.load32(memAddr); ps.memory.store16(memAddr, regs.get(Rm)); - + //according to the ARM architecture reference, the value loaded from a memory address is rotated //according to the number of ones in the first two bits of the address regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - - private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements Interpreter.Instruction { + private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer + implements ARM_Instruction { + + /** the lowest address that we're reading a register from / writing a register to */ + private final int startAddress; + + /** An array that contains the registers to be transferd in ascending order. + * The list is delimited by setting the entry after the last register index to -1. + * The PC is not included in this list, if it shall be transferred. */ + private final int[] registersToTransfer = new int[16]; + + /** True if the PC should be transferred to, false otherwise. */ + private final boolean transferPC; + public BlockDataTransfer(int instr) { super(instr); - } - public void execute() { - //start address ignores the last two bits - int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + transferPC = transferRegister(15); + int registerCount = 0; - //build a map of registers that are to be transfered - int registerCount = 0; - boolean transferPC = false; - int[] registersToTransfer = new int[16]; - for (int i = 0; i < 14; i++) if (transferRegister(i)) { registersToTransfer[registerCount++] = i; } - - //also remember if we're supposed to transfer the pc, but don't include it in the register list - transferPC = transferRegister(15); - + + registersToTransfer[registerCount] = -1; + + //build the address, which generally ignores the last two bits if (!incrementBase) { - if (postIndexing) - startAddress -= (registerCount + (transferPC ? -1 : 0)) * 4; //post-indexing, backward reading - else - startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; //pre-indexing, backward-reading + if (postIndexing) { + //post-indexing, backward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC + - (registerCount + (transferPC ? -1 : 0)) * 4; + } else { + //pre-indexing, backward-reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC + - (registerCount + (transferPC ? 1 : 0)) * 4; + } + } else { + if (postIndexing) { + //post-indexing, forward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC - 4; + } else { + //pre-indexing, forward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + } } - else if (postIndexing) { - //post-indexing, forward reading - startAddress -= 4; - } - + } + + public void execute() { + int nextAddress = startAddress; + //are we supposed to load or store multiple registers? if (isLoad) { - //read the actual registers - for (int i = 0; i < registerCount; i++) { - startAddress += 4; - regs.set(registersToTransfer[i], ps.memory.load32(startAddress)); + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + nextAddress += 4; + regs.set(registersToTransfer[nextReg++], ps.memory + .load32(nextAddress)); } - + //if we also transferred the program counter if (transferPC) { - int newpc = ps.memory.load32(startAddress + 4); + nextAddress += 4; + int newpc = ps.memory.load32(nextAddress); regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - + //shall we switch to thumb mode regs.setThumbMode((newpc & 0x1) != 0); } - } - else { + } else { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + nextAddress += 4; + ps.memory.store32(nextAddress, regs + .get(registersToTransfer[nextReg++])); + } + //also transfer the program counter, if requested so - if (transferPC) - registersToTransfer[registerCount++] = 15; - - for (int i = 0; i < registerCount; i++) { - startAddress += 4; - ps.memory.store32(startAddress, regs.get(i)); + if (transferPC) { + nextAddress += 4; + ps.memory.store32(nextAddress, regs.get(15)); } } + + if (writeBack) { + //write the last address we read from back to a register + //TODO: Check if we have to consider the different cases? + if (!incrementBase) + nextAddress = startAddress; + + regs.set(baseRegister, nextAddress); + } } public int getSuccessor(int pc) { //if we're loading values into the PC, then we can't tell where this instruction will be going - if (isLoad && transferRegister(ARM_Registers.PC)) + if (isLoad && transferPC) return -1; else - return pc+4; + return pc + 4; } } - - private class Branch extends ARM_Instructions.Branch implements Interpreter.Instruction { + private class Branch extends ARM_Instructions.Branch implements + ARM_Instruction { + public Branch(int instr) { super(instr); } public void execute() { int previousAddress = regs.get(ARM_Registers.PC); - + //jump to the new address regs.set(ARM_Registers.PC, previousAddress + getOffset()); - + //if we're supposed to link, then write the previous address into the link register if (link) regs.set(ARM_Registers.LR, previousAddress + 4); } public int getSuccessor(int pc) { - return pc + getOffset(); + return pc + getOffset() + 8; } } - - private class BranchExchange extends ARM_Instructions.BranchExchange implements Interpreter.Instruction { + private class BranchExchange extends ARM_Instructions.BranchExchange + implements ARM_Instruction { + public BranchExchange(int instr) { super(instr); } @@ -551,13 +696,13 @@ int previousAddress = regs.get(ARM_Registers.PC); boolean thumb; int targetAddress; - + switch (target.getType()) { case PcRelative: targetAddress = previousAddress + target.getOffset(); thumb = true; break; - + case Register: targetAddress = regs.get(target.getRegister()); thumb = (targetAddress & 0x1) != 0; @@ -565,13 +710,14 @@ break; default: - throw new RuntimeException("Unexpected Operand type: " + target.getType()); + throw new RuntimeException("Unexpected Operand type: " + + target.getType()); } - + //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); - + //if we're supposed to link, then write the previous address into the link register if (link) regs.set(ARM_Registers.LR, previousAddress + 4); @@ -581,55 +727,41 @@ //if we're jumping relative to the PC, then we can predict the next instruction if (target.getType() == OperandWrapper.Type.PcRelative) { return pc + target.getOffset(); - } - else { + } else { //otherwise we can't predict it return -1; } } } - - private class CountLeadingZeros extends ARM_Instructions.CountLeadingZeros implements Interpreter.Instruction { - public CountLeadingZeros(int instr) { - super(instr); - } + private class IntMultiply extends ARM_Instructions.IntMultiply implements + ARM_Instruction { - public void execute() { - int leadingZeros = Integer.numberOfLeadingZeros(regs.get(Rm)); - regs.set(Rd, leadingZeros); - } - - public int getSuccessor(int pc) { - return pc+4; - } - } - - private class IntMultiply extends ARM_Instructions.IntMultiply implements Interpreter.Instruction { - protected IntMultiply(int instr) { super(instr); } public void execute() { int result = regs.get(Rm) * regs.get(Rs); - + if (accumulate) result += regs.get(Rn); - + regs.set(Rd, result); - + if (updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements Interpreter.Instruction { + private class MoveFromStatusRegister extends + ARM_Instructions.MoveFromStatusRegister implements + ARM_Instruction { public MoveFromStatusRegister(int instr) { super(instr); @@ -637,24 +769,24 @@ public void execute() { int statusRegisterValue; - + if (transferSavedPSR) { statusRegisterValue = regs.getSPSR(); - } - else { + } else { statusRegisterValue = regs.getCPSR(); } - + regs.set(Rd, statusRegisterValue); } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - - private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements Interpreter.Instruction { + private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + implements ARM_Instruction { + public SoftwareInterrupt(int instr) { super(instr); } @@ -666,33 +798,172 @@ public int getSuccessor(int pc) { return -1; } - + } - - private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements Interpreter.Instruction { + private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer + implements ARM_Instruction { + public SingleDataTransfer(int instr) { super(instr); } - public void execute() { + private int resolveAddress() { + + //acquire the base address + int base = regs.get(Rn); + //take ARM's PC offset into account + if (Rn == 15) + base += 8; + + //if we are not pre-indexing, then just use the base register for the memory access + if (!preIndexing) + return base; + + switch (offset.getType()) { + case Immediate: + if (positiveOffset) + return base + offset.getImmediate(); + else + return base - offset.getImmediate(); + + case Register: + int offsetRegister = regs.get(offset.getRegister()); + if (offset.getRegister() == ARM_Registers.PC) { + offsetRegister += 8; + } + + if (positiveOffset) + return base + offsetRegister; + else + return base - offsetRegister; + + case ImmediateShiftedRegister: + if (offset.getRegister() == 15) + throw new RuntimeException( + "PC-relative memory accesses are not yet supported."); + + int addrOffset = regs.get(offset.getRegister()); + + switch (offset.getShiftType()) { + case ASR: + addrOffset = addrOffset >>> offset.getShiftAmount(); + break; + + case LSL: + addrOffset = addrOffset << offset.getShiftAmount(); + break; + + case LSR: + addrOffset = addrOffset >> offset.getShiftAmount(); + break; + + case ROR: + addrOffset = Integer.rotateRight(addrOffset, offset.getShiftAmount()); + break; + + case RRE: + if (regs.isCarrySet()) + addrOffset = (addrOffset >> 1) | 0x80000000; + else + addrOffset = addrOffset >> 1; + break; + + default: + throw new RuntimeException("Unexpected shift type: " + + offset.getShiftType()); + } + + case PcRelative: + case RegisterShiftedRegister: + default: + throw new RuntimeException("Unexpected operand type: " + + offset.getType()); + } + } + public void execute() { + if (forceUserMode) { + //TODO: Implement user mode memory access + throw new RuntimeException( + "Forced user mode memory access is not yet supported."); + } + + int address = resolveAddress(); + + if (isLoad) { + int value; + + switch (size) { + case Byte: + if (signExtend) + value = ps.memory.loadSigned8(address); + else + value = ps.memory.loadUnsigned8(address); + break; + + case HalfWord: + if (signExtend) + value = ps.memory.loadSigned16(address); + else + value = ps.memory.loadUnsigned16(address); + break; + + case Word: + value = ps.memory.load32(address); + break; + + default: + throw new RuntimeException("Unexpected memory size: " + size); + } + + regs.set(Rd, value); + } else { + int value = regs.get(Rd); + + switch (size) { + case Byte: + ps.memory.store8(address, value); + break; + + case HalfWord: + ps.memory.store16(address, value); + break; + + case Word: + ps.memory.store32(address, value); + break; + + default: + throw new RuntimeException("Unexpected memory size: " + size); + } + } + + if (writeBack) { + if (preIndexing) + regs.set(Rn, address); + else { + //TODO: calculate the post-indexed address + //and set it to Rn + } + } + } + public int getSuccessor(int pc) { //if we're loading to the PC, then the next instruction is undefined - if (Rd == ARM_Registers.PC) + if (Rd == ARM_Registers.PC && isLoad) return -1; - - return pc+4; + + return pc + 4; } - } - - private class UndefinedInstruction implements Interpreter.Instruction { - + + private class UndefinedInstruction implements ARM_Instruction { + private final int instruction; - + public UndefinedInstruction(int instr) { this.instruction = instr; } @@ -704,12 +975,16 @@ public int getSuccessor(int pc) { return -1; } + + public Condition getCondition() { + return Condition.AL; + } } class InterpreterFactory implements - ARM_InstructionFactory<Interpreter.Instruction> { + ARM_InstructionFactory<ARM_Instruction> { - public Interpreter.Instruction createDataProcessing(int instr) { + public ARM_Instruction createDataProcessing(int instr) { Opcode opcode = Opcode.values()[Utils.getBits(instr, 21, 24)]; switch (opcode) { @@ -745,6 +1020,9 @@ return new DataProcessing_Teq(instr); case TST: return new DataProcessing_Tst(instr); + + case CLZ: + return new DataProcessing_Clz(instr); default: throw new RuntimeException("Unexpected Data Procesing opcode: " @@ -752,70 +1030,68 @@ } } - public Instruction createBlockDataTransfer(int instr) { + public ARM_Instruction createBlockDataTransfer(int instr) { return new BlockDataTransfer(instr); } - public Instruction createBranch(int instr) { + public ARM_Instruction createBranch(int instr) { return new Branch(instr); } - public Instruction createBranchExchange(int instr) { + public ARM_Instruction createBranchExchange(int instr) { return new BranchExchange(instr); } - public Instruction createCoprocessorDataProcessing(int instr) { + public ARM_Instruction createCoprocessorDataProcessing(int instr) { //TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCoprocessorDataTransfer(int instr) { -// TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + public ARM_Instruction createCoprocessorDataTransfer(int instr) { + // TODO: Implement coprocessor instructions + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCoprocessorRegisterTransfer(int instr) { -// TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { + // TODO: Implement coprocessor instructions + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCountLeadingZeros(int instr) { - return new CountLeadingZeros(instr); - } - - public Instruction createIntMultiply(int instr) { + public ARM_Instruction createIntMultiply(int instr) { return new IntMultiply(instr); } - public Instruction createLongMultiply(int instr) { + public ARM_Instruction createLongMultiply(int instr) { throw new RuntimeException("Long Multiplications are not yet supported."); } - public Instruction createMoveFromStatusRegister(int instr) { + public ARM_Instruction createMoveFromStatusRegister(int instr) { return new MoveFromStatusRegister(instr); } - public Instruction createMoveToStatusRegister(int instr) { + public ARM_Instruction createMoveToStatusRegister(int instr) { //TODO: Implement Register -> CPSR transfers - throw new RuntimeException("Modifying the status register using MSR is not yet supported."); + throw new RuntimeException( + "Modifying the status register using MSR is not yet supported."); } - public Instruction createSingleDataTransfer(int instr) { - // TODO Auto-generated method stub - return null; + public ARM_Instruction createSingleDataTransfer(int instr) { + return new SingleDataTransfer(instr); } - public Instruction createSoftwareInterrupt(int instr) { + public ARM_Instruction createSoftwareInterrupt(int instr) { return new SoftwareInterrupt(instr); } - public Instruction createSwap(int instr) { + public ARM_Instruction createSwap(int instr) { return new Swap(instr); } - public Instruction createUndefinedInstruction(int instr) { + public ARM_Instruction createUndefinedInstruction(int instr) { return new UndefinedInstruction(instr); } } - } Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-18 17:40:18 UTC (rev 69) @@ -20,7 +20,8 @@ } /** - * Extracts a subsequence of bits from a word. + * Extracts a subsequence of bits from a word and shifts the beginning of that subsequence to + * a zero based-number. * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. * @param word * The word that is to be examined. @@ -33,7 +34,8 @@ */ static final int getBits(int word, int from, int to) { if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); + DBT._assert(from < to && from >= 0 && to < 31); + return (word & ((1 << (to + 1)) - 1)) >> from; } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 17:40:18 UTC (rev 69) @@ -2,10 +2,11 @@ import java.io.IOException; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; @@ -14,18 +15,10 @@ public abstract class ARM_ProcessSpace extends ProcessSpace { - /* - * Instance data - */ - /** - * Registers used by this process - */ + /** Registers used by this process */ public ARM_Registers registers; - /* - * Utility functions - */ /** * Debug information @@ -40,16 +33,9 @@ } } - /* - * Methods - */ - - /** - * Constructor - */ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new ByteAddressedMemory(); + memory = new DebugMemory(); } /** @@ -82,13 +68,10 @@ return new ARM_ImageProcessSpace(); } } - - /** - * Run a single instruction - */ - public void runOneInstruction() throws BadInstructionException { - // TODO - throw new RuntimeException("Not yet implemented"); + + @Override + public Interpreter createInstructionInterpreter() throws UnsupportedOperationException { + return new ARM_Interpreter(this); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-18 17:40:18 UTC (rev 69) @@ -198,5 +198,20 @@ public boolean isCarrySet() { return flagCarry; } + + /** Returns true if the zero flag is set, false otherwise. */ + public boolean isZeroSet() { + return flagZero; + } + + /** Returns true if the overflow flag is set, false otherwise. */ + public boolean isOverflowSet() { + return flagOverflow; + } + + /** Returns true if the negative flag is set, false otherwise. */ + public boolean isNegativeSet() { + return flagNegative; + } } Added: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java (rev 0) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-18 17:40:18 UTC (rev 69) @@ -0,0 +1,31 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public class InterpreterController extends ExecutionController { + + public InterpreterController(ProcessSpace ps) { + super(ps); + } + + @Override + public void run() { + Interpreter interpreter = ps.createInstructionInterpreter(); + int pc = ps.getCurrentInstructionAddress(); + + while (!ps.finished) { + + Interpreter.Instruction instruction = interpreter.decode(pc); + pc = instruction.getSuccessor(pc); + + System.out.println("Interpreting instruction: " + instruction.toString()); + + instruction.execute(); + + if (pc == -1) + pc = ps.getCurrentInstructionAddress(); + } + } + +} Added: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java (rev 0) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-18 17:40:18 UTC (rev 69) @@ -0,0 +1,539 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.memory; + +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.vmInterface.TranslationHelper; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; + +/** + * A copy of byte-addressed memory, that does not allow the translation of accesses to bytecode. + * This is stricly for debugging purposes, as it allows the Pearcolator interpreter to be executed + * in a windows environment. + */ +public class DebugMemory extends Memory { + /** + * The size of pages + */ + private static final int PAGE_SIZE = 4096; + + /** + * Bits in offset + */ + private static final int OFFSET_BITS = 12; + + /** + * The number of pages + */ + private static final int NUM_PAGES = 0x100000; + + /** + * The maximum amount of RAM available + */ + protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; + + /** + * The memory backing store + */ + private byte readableMemory[][]; + + private byte writableMemory[][]; + + private byte executableMemory[][]; + + /** + * Do we have more optimal nio mmap operation? + */ + private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; + + /** + * Constructor - used when this is the instatiated class + */ + public DebugMemory() { + readableMemory = new byte[NUM_PAGES][]; + writableMemory = new byte[NUM_PAGES][]; + executableMemory = new byte[NUM_PAGES][]; + } + + /** + * Return the offset part of the address + */ + private static final int getOffset(int address) { + return address & (PAGE_SIZE - 1); + } + + /** + * Return the page table entry part of the address + */ + private static final int getPTE(int address) { + return address >>> OFFSET_BITS; + } + + /** + * Find free consecutive pages + * + * @param pages + * the number of pages required + * @return the address found + */ + private final int findFreePages(int pages) { + starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { + if ((readableMemory[i] == null) && (writableMemory[i] == null) + && (executableMemory[i] == null)) { + int start = i; + int end = i + pages; + for (; i <= end; i++) { + if ((readableMemory[i] != null) || (writableMemory[i] != null) + || (executableMemory[i] != null)) { + continue starting_page_search; + } + } + return start << OFFSET_BITS; + } + } + throw new Error( + "No mappable consecutive pages found for an anonymous map of size" + + (pages * PAGE_SIZE)); + } + + /** + * Map an anonymous page of memory + * + * @param addr + * the address to map or NULL if don't care + * @param len + * the amount of memory to map + * @param read + * is the page readable + * @param write + * is the page writable + * @param exec + * is the page executable + */ + public int map(int addr, int len, boolean read, boolean write, boolean exec) + throws MemoryMapException { + // Check address is page aligned + if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + } + // Create memory + int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + byte pages[][] = new byte[num_pages][PAGE_SIZE]; + // Find address if not specified + if (addr == 0) { + addr = findFreePages(num_pages); + } + if (DBT_Options.debugMemory) { + System.err.println("Anonymous mapping: addr=0x" + + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + + (write ? "w" : "-") + (exec ? "x" : "-")); + } + // Get page table entry + int pte = getPTE(addr); + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate pages + if (read) { + readableMemory[pte + i] = pages[i]; + } + if (write) { + writableMemory[pte + i] = pages[i]; + } + if (exec) { + executableMemory[pte + i] = pages[i]; + } + } + return addr; + } + + /** + * Map a page of memory from file + * + * @param file + * the file map in from + * @param addr + * the address to map or NULL if don't care + * @param len + * the amount of memory to map + * @param read + * is the page readable + * @param write + * is the page writable + * @param exec + * is the page executable + */ + public int map(RandomAccessFile file, long offset, int addr, int len, + boolean read, boolean write, boolean exec) throws MemoryMapException { + // Check address is page aligned + if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + } + // Check file offset is page aligned + /* + if ((offset % PAGE_SIZE) != 0) { + MemoryMapException.unalignedFileOffset(offset); + } + */ + + // Calculate number of pages + int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + // Find address if not specified + if (addr == 0) { + addr = findFreePages(num_pages); + } + if (DBT_Options.debugMemory) { + System.err.println("Mapping file " + file + " offset=" + offset + + " addr=0x" + Integer.toHexString(addr) + " len=" + len + + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); + } + try { + // Get page table entry + int pte = getPTE(addr); + // Can we optimise the reads to use mmap? + if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) { + // Sub-optimal + file.seek(offset); + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate page + byte page[] = new byte[PAGE_SIZE]; + if (i == 0) { // first read, start from offset upto a page length + file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr)); + } else if (i == (num_pages - 1)) { // last read + file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE)); + } else { + file.read(page); + } + if (read) { + readableMemory[pte + i] = page; + } + if (write) { + writableMemory[pte + i] = page; + } + if (exec) { + executableMemory[pte + i] = page; + } + } + } else { + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate page + if (read && write) { + readableMemory[pte + i] = file.getChannel().map( + FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), + P... [truncated message content] |
From: <mic...@us...> - 2007-04-24 18:16:44
|
Revision: 90 http://svn.sourceforge.net/pearcolator/?rev=90&view=rev Author: michael_baer Date: 2007-04-24 11:16:44 -0700 (Tue, 24 Apr 2007) Log Message: ----------- - First version that runs ARM "Hello World" (compiled with libc) - Fixed several bugs related to ARM flags - Introduced the munmap system call within for the ARM ABI - Calls to memory.map may provide non-page aligned memory addresses - Introduced the stat64 structure Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/Main.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,7 @@ import java.io.File; +import org.binarytranslator.arch.arm.decoder.Utils; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; @@ -93,17 +94,19 @@ System.out.println("***** INITIAL PROCESS SPACE *****\n"); System.out.println(ps); } - + //Create an execution controller and pass execution on to it ExecutionController controller; - if (DBT_Options.gdbStub) { + /*if (DBT_Options.gdbStub) { controller = new GdbController(DBT_Options.gdbStubPort, ps); } else { controller = new DynamicTranslationController(ps); - } + }*/ + controller = new InterpreterController(ps); + controller.run(); } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-24 18:16:44 UTC (rev 90) @@ -107,13 +107,13 @@ return regs.isNegativeSet() == regs.isOverflowSet(); case GT: - return (regs.isNegativeSet() == regs.isOverflowSet()) && regs.isZeroSet(); + return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); case HI: return regs.isCarrySet() && !regs.isZeroSet(); case LE: - return regs.isZeroSet() || (regs.isNegativeSet() == regs.isOverflowSet()); + return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); case LS: return !regs.isCarrySet() || regs.isZeroSet(); @@ -347,8 +347,8 @@ if (updateConditionCodes) { if (Rd != 15) { int result = lhs - rhs; - boolean carry = !(lhs < rhs); - boolean overflow = Utils.signedAddOverflow(lhs, -rhs); + boolean carry = !Utils.unsignedSubOverflow(lhs, rhs); + boolean overflow = Utils.signedSubOverflow(lhs, rhs); regs.setFlags(result < 0, result == 0, carry, overflow); } else { Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-24 18:16:44 UTC (rev 90) @@ -2,7 +2,7 @@ import org.binarytranslator.DBT; -class Utils { +public class Utils { /** * Checks if a bit is set within a word. @@ -54,33 +54,124 @@ /** * Returns true, if the addition of both operands as unsigned integers will cause an overflow. - * This basically checks <code> operand1 + operand2 > Integer.MAX_VALUE</code>. + * At the moment, this converts both values to longs and checks if the 33rd bit (which actually represents the carry) + * overflows. */ - static boolean unsignedAddOverflow(int operand1, int operand2) { - return operand1 > Integer.MAX_VALUE - operand2; + public static boolean unsignedAddOverflow(int operand1, int operand2) { + long value1 = (long)operand1 & 0xFFFFFFFFL; + long value2 = (long)operand2 & 0xFFFFFFFFL; + + return ((value1 + value2) & 0x100000000L) != 0; } /** - * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will be a negative number. - * That only happens when <code>operand1 < operand2</code> + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will issue a borrow. */ - static boolean unsignedSubOverflow(int operand1, int operand2) { + public static boolean unsignedSubOverflow(int operand1, int operand2) { + operand1 += Integer.MIN_VALUE; + operand2 += Integer.MIN_VALUE; + return operand1 < operand2; } /** - * Returns true, if the addition of both operands as unsigned integers will cause an overflow. - * The algorithm for this code was taken from http://msdn2.microsoft.com/en-us/library/ms972705.aspx. + * Returns true, if the addition of both operands as signed integers will cause an overflow. + * This basically checks <code>operand1 + operand2 > Integer.MAX_VALUE</code>. */ - static boolean signedAddOverflow(int operand1, int operand2) { - //overflow can only occur when both signs differ - if ((operand1 ^ operand2) >= 0) { - return false; + public static boolean signedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of operand1 from operand (as signed integers) + * will cause an overflow. + * This basically checks <code>operand1 - operand2 < Integer.MIN_VALUE</code>. + */ + public static boolean signedSubOverflow(int operand1, int operand2) { + // if the MSB is already set in any of the operands, then no overflow can + // occur + if (operand1 >= 0) { + return (operand2 < 0) && ((operand1-operand2) < 0); } + else { + return (operand2 > 0) && ((operand1-operand2) > 0); + } + } + + /** + * Performs a number of sanity tests that make sure that the above functions are working the + * manner described before.*/ + public static void runSanityTests() { + if (!Utils.unsignedAddOverflow(1, -1)) { + throw new RuntimeException("Error"); + } - if (operand1 < 0) - return operand1 < Integer.MIN_VALUE - operand2; - else - return Integer.MAX_VALUE - operand1 < operand2; + if (!Utils.unsignedAddOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedAddOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedAddOverflow(10000, 10000)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(10, 0)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(0, 10)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x70000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x90000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x50000000, 0x50000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x60000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x10000000, 0x60000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x80000000, 0x30000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x30000000, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedSubOverflow(0, 0x70000000)) { + throw new RuntimeException("Error"); + } } } Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) @@ -1,11 +1,14 @@ package org.binarytranslator.arch.arm.os.abi.linux; +import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; public class ARM_LinuxSystemCalls extends LinuxSystemCalls { - public ARM_LinuxSystemCalls(LinuxSystemCallGenerator src) { + private final ARM_LinuxProcessSpace ps; + + public ARM_LinuxSystemCalls(ARM_LinuxProcessSpace ps, LinuxSystemCallGenerator src) { super(src); systemCallTable[1] = new LinuxSystemCalls.SysExit(); @@ -19,6 +22,7 @@ systemCallTable[49] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[50] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[90] = new LinuxSystemCalls.SysMmap(); + systemCallTable[91] = new LinuxSystemCalls.SysMunmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); @@ -28,8 +32,16 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); + + this.ps = ps; } + + @Override + public void doSysCall() { + super.doSysCall(); + } + @Override protected String getMachine() { //TODO: Grab this from a real machine Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-24 18:16:44 UTC (rev 90) @@ -4,6 +4,7 @@ public final class ARM_Registers { + public final static int FP = 11; public final static int SP = 13; public final static int LR = 14; public final static int PC = 15; Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-24 18:16:44 UTC (rev 90) @@ -28,18 +28,13 @@ private static final int STACK_TOP = 0xC0000000; /** - * The top of the bss segment - */ - private int brk; - - /** * Auxiliary vector */ private int[] auxVector; public ARM_LinuxProcessSpace() { - sysCallGenerator = new Legacy(this); - sysCalls = new ARM_LinuxSystemCalls(sysCallGenerator); + sysCallGenerator = new Legacy(this, 0xEBADADD); + sysCalls = new ARM_LinuxSystemCalls(this, sysCallGenerator); } @Override @@ -54,31 +49,52 @@ @Override public void initialise(Loader loader, int pc, int brk) { registers.set(ARM_Registers.PC, pc); - this.brk = brk; + sysCallGenerator.setBrk(brk); // initialize the stack - auxVector = new int[]{//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, - //LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, - LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, - LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, - LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), - LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, + auxVector = new int[] { + LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x97, + LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 4096, //0x100 + LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x17, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0x8034, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6, + LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x40000000, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, - LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, + LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, 0x82b4, + LinuxStackInitializer.AuxiliaryVectorType.AT_UID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_GID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, 0x0, + LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd }; - LinuxStackInitializer.AuxiliaryVectorType.AT_UID, DBT_Options.UID, - LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, DBT_Options.UID, - LinuxStackInitializer.AuxiliaryVectorType.AT_GID, DBT_Options.GID, - LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, DBT_Options.GID, - - LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, - //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, - LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } + + public void dumpStack() { + //grab the current frame pointer + int fp = registers.get(ARM_Registers.FP); + + //print the current position + System.out.println("PC: 0x" + Integer.toHexString(registers.get(ARM_Registers.PC))); + + //we might be in a leaf function which did not create a stack frame. Check that by + //comparing the current link register with the one saved on the first stack frame + int saved_lr = memory.load32(fp - 4); + int processor_lr = registers.get(ARM_Registers.LR); + + if (saved_lr != processor_lr) { + //we are in a leaf function that did not generate a stack frame. Print out the function address + System.out.println("Called from 0x" + Integer.toHexString(processor_lr - 4) + " (Function did not create a stack frame)."); + } + + do { + saved_lr = memory.load32(fp - 4); //load the link register, so we know where we're called from + fp = memory.load32(fp - 12); //load the previous frame pointer + System.out.println("Called from 0x" + Integer.toHexString(saved_lr - 4)); + } + while (fp != 0); + } @Override public GdbTarget getGdbTarget() { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-24 18:16:44 UTC (rev 90) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.os.process.linux.abi; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -28,15 +29,16 @@ /** The process space that we're running on. */ private final ARM_LinuxProcessSpace ps; private final ArgumentIterator args; + private int brk; - public EABI(ARM_LinuxProcessSpace ps) { + public EABI(ARM_LinuxProcessSpace ps, int brk) { this.ps = ps; + this.brk = brk; this.args = new ArgumentIterator(); } public int getBrk() { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + return brk; } public ProcessSpace getProcessSpace() { @@ -53,8 +55,16 @@ } public void setBrk(int address) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + + try { + ps.memory.ensureMapped(brk, address); + } catch (MemoryMapException e) { + throw new Error(String.format( + "Error changing top of BSS from 0x%x to address 0x%x", brk, address), + e); + } + + brk = address; } public void setSysCallError(int r) { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-24 18:16:44 UTC (rev 90) @@ -4,6 +4,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -30,21 +31,29 @@ /** A re-used iterator that allows enumerating the argument of the current * system call */ private final ArgumentIterator syscallArgs; + + private int brk; - public Legacy(ARM_LinuxProcessSpace ps) { + public Legacy(ARM_LinuxProcessSpace ps, int brk) { this.ps = ps; + this.brk = brk; syscallArgs = new ArgumentIterator(); } public int getBrk() { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + return brk; } public void setBrk(int address) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + try { + ps.memory.ensureMapped(brk, address); + } catch (MemoryMapException e) { + throw new Error("Error changing top of BSS to address 0x"+Integer.toHexString(address)+ + " from 0x" + Integer.toHexString(brk), e); + } + + brk = address; } public ProcessSpace getProcessSpace() { Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,8 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; + +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.compilers.opt.ir.OPT_Operand; @@ -121,10 +123,21 @@ */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned + // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); + // if it is not, truncate the address down to the next page boundary and + // start mapping from there + int validPageCount = addr / PAGE_SIZE; + int oldStartAddress = addr; + addr = validPageCount * PAGE_SIZE; + + if (DBT.VerifyAssertions) + DBT._assert(oldStartAddress > addr); + + // we have to map more more memory now to reach the same end address + len += (oldStartAddress - addr); } + // Create memory int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; byte pages[][] = new byte[num_pages][PAGE_SIZE]; Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -10,6 +10,7 @@ import java.io.RandomAccessFile; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.jikesrvm.VM_Configuration; @@ -191,10 +192,21 @@ */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned + // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); + // if it is not, truncate the address down to the next page boundary and + // start mapping from there + int validPageCount = addr / PAGE_SIZE; + int oldStartAddress = addr; + addr = validPageCount * PAGE_SIZE; + + if (DBT.VerifyAssertions) + DBT._assert(oldStartAddress > addr); + + // we have to map more more memory now to reach the same end address + len += (oldStartAddress - addr); } + // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; // Create memory Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -251,4 +251,41 @@ throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); } + + /** + * Helper function that prints a hexadecimal version of a memory region. + * Quite useful for debugging. + * @param address + * The address to start printing from. + * @param length + * The number of bytes to print from <code>address</code>. + * @return + * A string with a hexdecimal representation of that memory region. + * The string is only useful for printing, no assumptions about its format + * shall be made. + */ + public String hexDump(int address, int length) { + + StringBuilder output = new StringBuilder(); + int printed = 0; + + while (printed != length) { + + //make a line break and print the current address every 8 bytes + if (printed % 8 == 0) { + if (printed != 0) + output.append('\n'); + + output.append("[0x"); + output.append(Integer.toHexString(address)); + output.append("] "); + } + + output.append(String.format("%02x", loadUnsigned8(address++))); + output.append(' '); + printed++; + } + + return output.toString(); + } } \ No newline at end of file Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStructureFactory.java 2007-04-24 18:16:44 UTC (rev 90) @@ -5,17 +5,28 @@ import org.binarytranslator.generic.memory.Memory; -/** Namespace for all structures. */ +/** + * Linux heavily uses certain c-structs when to pass parameters for system calls. + * To allow the pearcolator linux ABIs to share a common set of structure definitions, this + * namespace provides a factory for Java representations of the most commonly used structures. + * Each structure provides methods to read the structure from or write it to memory. + * + * @author Michael Baer + */ public class LinuxStructureFactory { + /** A factory method which will create a stat64 structure.*/ public final stat64 new_stat64() { return new stat64(); } + /** + * The stat64 structure, as defined in <code>include\linux\stat64.h</code>. + */ public class stat64 extends Structure { @_unsigned short st_dev; @_unsigned @_padding(10) byte __pad0; - @_unsigned @_long long __st_ino; + @_unsigned long __st_ino; @_unsigned int st_mode; @_unsigned int st_nlink; @_unsigned long st_uid; @@ -34,11 +45,80 @@ @_unsigned @_padding(1) long __pad7; @_unsigned @_long long st_ino; - public stat64() { + /** + * At the moment, we have to enumerate the members of a structure in the constructor + * (in the order of definition within the c file), because the JVM specs say that no code shall + * rely on the order of the fields returned by reflection methods (namely {@link Class#getFields()}. + * + * Therefore, we have to persist the order of fields, which is why we are enumerating them again. + * However, this is not necessary the final solution. Possibly we're going to introduce a + * Java annotation that keeps the information about the order - or we might even solve the problem + * completely differently. + * + */ + protected stat64() { super(new String[]{ "st_dev", "__pad0", "__st_ino", "st_mode", "st_nlink", "st_uid", "st_gid", "st_rdev", "__pad3", "st_size", "st_blksize", "st_blocks", "__pad4", "st_atime", "__pad5", "st_mtime", "__pad6", "st_ctime", "__pad7", "st_ino"}); } + + /** This overriden structure enables Michael to debug the pearcolator in windows. + * Otherwise, it should not be used, which is why it is deprecated. */ + @Override + @Deprecated + public void read(Memory mem, int addr) { + StructureAdapter reader = createStructureAdapter(mem, addr); + + st_dev = reader.loadShort(); + reader.skipPadding(10); + __st_ino = reader.loadLong(); + st_mode = reader.loadInt(); + st_nlink = reader.loadInt(); + st_uid = reader.loadLong(); + st_gid = reader.loadLong(); + st_rdev = reader.loadShort(); + reader.skipPadding(10); + st_size = reader.loadLongLong(); + st_blksize = reader.loadLong(); + st_blocks = reader.loadLong(); + __pad4 = reader.loadLong(); + st_atime = reader.loadLong(); + __pad5 = reader.loadLong(); + st_mtime = reader.loadLong(); + __pad6 = reader.loadLong(); + st_ctime = reader.loadLong(); + __pad7 = reader.loadLong(); + st_ino = reader.loadLongLong(); + } + + /** + * This overriden structure enables Michael to debug the pearcolator in windows. + * Otherwise, it should not be used, which is why it is deprecated. */ + @Override + @Deprecated + public void write(Memory mem, int addr) { + StructureAdapter writer = createStructureAdapter(mem, addr); + writer.storeShort(st_dev); + writer.skipPadding(10); + writer.storeLong(__st_ino); + writer.storeInt(st_mode); + writer.storeInt(st_nlink); + writer.storeLong(st_uid); + writer.storeLong(st_gid); + writer.storeShort(st_rdev); + writer.skipPadding(10); + writer.storeLongLong(st_size); + writer.storeLong(st_blksize); + writer.storeLong(st_blocks); + writer.storeLong(__pad4); + writer.storeLong(st_atime); + writer.storeLong(__pad5); + writer.storeLong(st_mtime); + writer.storeLong(__pad6); + writer.storeLong(st_ctime); + writer.storeLong(__pad7); + writer.storeLongLong(st_ino); + } } private @interface _long {} @@ -50,9 +130,18 @@ /** A list of all structure members in the order that they appear in the source code. */ protected Field[] members; + /** + * This constructor is uncommented because reflection does not work when debugging pearcolator + * under windows, which is what I (=Michael Baer) am currently doing. + * + * However, as soon as this is done, the deprecated-tag shall be removed and the code in this + * function be uncommented. + * @param memberNames + */ + @Deprecated protected Structure(String[] memberNames) { - Class myType = getClass(); + /*Class myType = getClass(); members = new Field[memberNames.length]; for (int i = 0; i < memberNames.length; i++) { @@ -63,9 +152,17 @@ catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field: " + memberNames[i] + " in struct: " + myType.getSimpleName(), e); } - } + }*/ } + /** + * Read all members of this structure from memory into the structure. + * + * @param mem + * The memory that the structure is read from. + * @param addr + * The address of the structure's beginning in the memory. + */ public void read(Memory mem, int addr) { // get a structure writer, which will keep track of the object offsets @@ -112,6 +209,14 @@ } } + /** + * Writes the contents of the structure from its members into memory. + * + * @param mem + * The Memory into which the structure shall be written. + * @param addr + * The address, to which the structure is written. + */ public void write(Memory mem, int addr) { // get a structure writer, which will keep track of the object offsets @@ -165,6 +270,8 @@ } } + /** + * Converts a structure into a c-like, human readable format */ @Override public String toString() { @@ -193,10 +300,32 @@ } } + /** + * A factory method that creates a {@link StructureAdapter}. StructureAdapters are used to + * encapsulate the architecture specifics (like <code>sizeof(int)</code> and padding) when + * reading a structure. + * + * Implement your own StructureAdapter when you need to override the default implementations of + * how a structure is being read, while still keeping the default structures defined here. + * + * @param mem + * @param addr + * @return + */ protected final StructureAdapter createStructureAdapter(Memory mem, int addr) { - return new DefaultStructureAdapter(mem, addr); + return new StructureAdapter_32Bit(mem, addr); } + /** + * A StructureAdapter abstracts the properties (size, padding, maybe endianess) of the elements + * within a structure. Provide an own implementation of this class when the default data sizes + * and member alignments are not suitable for your architecture. + * + * Structures are always being read in the order of element definition. Therefore, any implementation + * of StructureAdapter can rely on the load/store functions being called in order, from the first + * to the last structure element. + * + */ protected static abstract class StructureAdapter { public abstract byte loadByte(); @@ -211,15 +340,51 @@ public abstract void storeLong(long value); public abstract void storeLongLong(long value); + /** + * Some structures contain rather large padding fields. To prevent use from reading these from + * memory byte-by-byte, this function may be used to skip a padding of type <code>field</code> + * that occurs <code>count</code> times. + * + * For example, when skipping a member like this <code>char pad[10]</char> the <code>field</code> + * would identify this as a char field, while the <code>count</code> member would say that we want + * to skip the char 10 times. + * + * @param field + * The type of the field that is being skipped. + * @param count + * The number of times this field as a padding in the structure. + */ public abstract void skipPadding(Field field, int count); + + /** + * This function is used temporarly to debug pearcolator in windows. However, + * it should normally not be invoked and as soon as windows-debugging is done, this + * function shall be removed from the source (along with all invokations of it).*/ + @Deprecated + public abstract void skipPadding(int count); } - protected static class DefaultStructureAdapter extends StructureAdapter { + /** + * A default implementation of a structure adapter. It has the following properties: + * + * <ul> + * <li>Every member is memory aligned to its size (i.e. a 4-byte data type is aligned to 4-byte + * boundaries</li> + * <li>The minimal needed amount of padding is inserted where the member is not already + * aligned to its size.</li> + * <li><code>sizeof(int) == 4</code></li> + * <li><code>sizeof(long) == 4</code></li> + * <li><code>sizeof(long long) == 8</code></li> + * <li><code>sizeof(short) == 2</code></li> + * <li><code>sizeof(byte) == 1</code></li> + * </ul> + */ + protected static class StructureAdapter_32Bit extends StructureAdapter { private final Memory mem; private int addr; - public DefaultStructureAdapter(Memory mem, int addr) { + public StructureAdapter_32Bit(Memory mem, int addr) { this.mem = mem; this.addr = addr; } @@ -350,5 +515,10 @@ return; } } + + @Override + public void skipPadding(int count) { + addr += count; + } } } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-23 22:12:34 UTC (rev 89) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-24 18:16:44 UTC (rev 90) @@ -23,13 +23,13 @@ /** * The source of the system calls */ - private LinuxSystemCallGenerator src; + protected LinuxSystemCallGenerator src; /** Allows access to the system call's arguments */ - private LinuxSystemCallGenerator.CallArgumentIterator arguments; + protected LinuxSystemCallGenerator.CallArgumentIterator arguments; /** Allows access to a number of operating-system specific structures. */ - private LinuxStructureFactory structures; + protected LinuxStructureFactory structures; /** * Maximum number of system calls @@ -802,9 +802,18 @@ int fd = arguments.nextInt(); LinuxStructureFactory.stat64 buf = structures.new_stat64(); - buf.read(src.getProcessSpace().memory, arguments.nextInt()); - System.out.println(buf.toString()); + if (fd == 1) { + buf.st_mode = 0x2180; + buf.st_rdev = (short)0x8800; + buf.__st_ino = buf.st_ino = 2; + buf.st_blksize = 0x400; + } + else + throw new RuntimeException("Unimplemented system call."); + + buf.write(src.getProcessSpace().memory, arguments.nextInt()); + src.setSysCallReturn(0); } } @@ -893,8 +902,9 @@ int start = arguments.nextInt(); int length = arguments.nextInt(); - throw new Error("TODO!"); - //src.setSysCallReturn(src.munmap(start, length)); + + src.getProcessSpace().memory.unmap(start, length); + src.setSysCallReturn(0); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-26 20:27:45
|
Revision: 94 http://svn.sourceforge.net/pearcolator/?rev=94&view=rev Author: michael_baer Date: 2007-04-26 13:27:47 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - Introduced processor mode handling to the ARM interpreter - Fixed decoder bug related to BLX - Several minor ARM fixes - First interpreter version that can run an ARM monitor Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/MemoryMapException.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-26 20:27:47 UTC (rev 94) @@ -357,7 +357,7 @@ public void visit(BranchExchange instr) { String mnemonic = instr.link ? "BLX" : "BX"; - setResult(String.format("%s%s #%d", mnemonic, cond(instr), operand(instr + setResult(String.format("%s%s #%s", mnemonic, cond(instr), operand(instr .target()))); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-26 20:27:47 UTC (rev 94) @@ -69,7 +69,8 @@ return factory.createMoveFromStatusRegister(instr); } - if (bits_7_4 == 1 && ((instr & 0x01F00000) == 0x01200000)) { + if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { + //bits 7-4 == 1 || bits 7-4 == 3 //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false return factory.createBranchExchange(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-26 20:27:47 UTC (rev 94) @@ -1157,7 +1157,7 @@ sourceOperand = OperandWrapper.decodeDataProcessingOperand(instr); } - /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ + /** Identifies the PSR that is to be overwritten: true for the SPSR, false for the CPSR. */ public final boolean transferSavedPSR() { return transferSavedPSR; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-26 20:27:47 UTC (rev 94) @@ -7,6 +7,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.decoder.Interpreter; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; @@ -48,6 +49,288 @@ return instruction; } + + private abstract static class ResolvedOperand { + + protected int value; + + public static ResolvedOperand resolveWithShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(regs, operand); + return result; + } + + public static int resolve(ARM_Registers regs, OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut(regs, operand); + return result.getValue(); + } + + public final int getValue() { + return value; + } + + public abstract boolean getShifterCarryOut(); + + private static class ResolvedOperand_WithoutShifterCarryOut + extends ResolvedOperand{ + + private ResolvedOperand_WithoutShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + _resolve(regs, operand); + } + + public boolean getShifterCarryOut() { + throw new RuntimeException("This class does not provide a shifter carry out value."); + } + + private void _resolve(ARM_Registers regs, OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = operand.getImmediate(); + return; + + case Register: + int reg = operand.getRegister(); + + //mind the arm pc offset + value = regs.get(reg); + + if (reg == 15) + value += 8; + + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(regs, operand); + return; + + case PcRelative: + value = regs.get(ARM_Registers.PC) + 8 + operand.getOffset(); + break; + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + private final int resolveShift(ARM_Registers regs, OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || + operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + int value = regs.get(operand.getRegister()); + + //consider the "usual" ARM program counter offset + if (operand.getRegister() == ARM_Registers.PC) + value += 8; + + byte shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) + shiftAmount = operand.getShiftAmount(); + else { + shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + } + + switch (operand.getShiftType()) { + case ASR: + + if (shiftAmount >= 32) { + return Utils.getBit(value, 31) ? 0xFFFFFFFF : 0; + } + return value >> shiftAmount; + + case LSL: + + if (shiftAmount >= 32) { + return 0; + } + + return value << shiftAmount; + + case LSR: + + if (shiftAmount >= 32) { + return 0; + } + + return value >>> shiftAmount; + + case ROR: + return Integer.rotateRight(value, shiftAmount); + + case RRE: + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + } + + private static class ResolvedOperand_WithShifterCarryOut + extends ResolvedOperand{ + + private boolean shifterCarryOut; + + private ResolvedOperand_WithShifterCarryOut(ARM_Registers regs, OperandWrapper operand) { + _resolve(regs, operand); + } + + public boolean getShifterCarryOut() { + return shifterCarryOut; + } + + private void _resolve(ARM_Registers regs, OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = operand.getImmediate(); + + if (operand.getShiftAmount() == 0) + shifterCarryOut = regs.isCarrySet(); + else + shifterCarryOut = (value & 0x80000000) != 0; + + return; + + case Register: + shifterCarryOut = regs.isCarrySet(); + int reg = operand.getRegister(); + + //mind the arm pc offset + value = regs.get(reg); + + if (reg == 15) + value += 8; + + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(regs, operand); + return; + + case PcRelative: + throw new RuntimeException("This operand type does not produce a shifter carry out."); + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + private final int resolveShift(ARM_Registers regs, OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || + operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + int value = regs.get(operand.getRegister()); + + //consider the "usual" ARM program counter offset + if (operand.getRegister() == ARM_Registers.PC) + value += 8; + + byte shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) + shiftAmount = operand.getShiftAmount(); + else { + shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + } + + switch (operand.getShiftType()) { + case ASR: + + if (shiftAmount >= 32) { + shifterCarryOut = Utils.getBit(value, 31); + return shifterCarryOut ? 0xFFFFFFFF : 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + + case LSL: + + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + + case LSR: + + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; + + case ROR: + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } + else { + shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); + return Integer.rotateRight(value, shiftAmount); + } + + case RRE: + shifterCarryOut = (value & 0x1) != 0; + + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + } + } + /** All ARM interpreter instructions implement this interface. */ private interface ARM_Instruction extends Interpreter.Instruction { /** Returns the condition, under which the given instruction will be executed. */ @@ -164,105 +447,8 @@ /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift * and set the result of the barrel shifter accordingly. */ - private final int resolveShift(OperandWrapper operand) { - if (DBT.VerifyAssertions) - DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || - operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); - - //consider the "usual" ARM program counter offset - if (operand.getRegister() == ARM_Registers.PC) - value += 8; - - byte shiftAmount; - if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) - shiftAmount = operand.getShiftAmount(); - else { - shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); - } - - switch (operand.getShiftType()) { - case ASR: - - if (shiftAmount >= 32) { - shifterCarryOut = Utils.getBit(value, 31); - return shifterCarryOut ? 0xFFFFFFFF : 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >> shiftAmount; - - case LSL: - - if (shiftAmount > 32) { - shifterCarryOut = false; - return 0; - } - - if (shiftAmount == 32) { - shifterCarryOut = Utils.getBit(value, 31); - return 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); - return value << shiftAmount; - - case LSR: - - if (shiftAmount > 32) { - shifterCarryOut = false; - return 0; - } - - if (shiftAmount == 32) { - shifterCarryOut = Utils.getBit(value, 31); - return 0; - } - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } - - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >>> shiftAmount; - - case ROR: - - if (shiftAmount == 0) { - shifterCarryOut = regs.isCarrySet(); - return value; - } else { - shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); - return Integer.rotateRight(value, shiftAmount); - } - - case RRE: - shifterCarryOut = (value & 0x1) != 0; - - if (regs.isCarrySet()) - return (value >> 1) | 0x80000000; - else - return value >> 1; - - default: - throw new RuntimeException("Unexpected shift type: " - + operand.getShiftType()); - } - } - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. * However, deriving classes may alter this behavior, for example to return a negative register * value for a RSB instruction. */ @@ -277,38 +463,9 @@ /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { - int value; - - switch (operand2.getType()) { - case Immediate: - value = operand2.getImmediate(); - - if (operand2.getShiftAmount() == 0) - shifterCarryOut = regs.isCarrySet(); - else - shifterCarryOut = (value & 0x80000000) != 0; - - return value; - - case Register: - shifterCarryOut = regs.isCarrySet(); - int reg = operand2.getRegister(); - - //mind the arm pc offset - if (reg == 15) - return regs.get(reg) + 8; - else - return regs.get(operand2.getRegister()); - - case RegisterShiftedRegister: - case ImmediateShiftedRegister: - return resolveShift(operand2); - - case PcRelative: - default: - throw new RuntimeException("Unexpected wrapped operand type: " - + operand2.getType()); - } + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = resolvedOperand2.getShifterCarryOut(); + return resolvedOperand2.getValue(); } public abstract void execute(); @@ -675,17 +832,26 @@ public void execute() { int memAddr = regs.get(Rn); - + //swap exchanges the value of a memory address with the value in a register - int tmp = ps.memory.load32(memAddr); - ps.memory.store16(memAddr, regs.get(Rm)); - - //according to the ARM architecture reference, the value loaded from a memory address is rotated - //according to the number of ones in the first two bits of the address - regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + if (swapByte) { + int tmp = ps.memory.load32(memAddr); + ps.memory.store32(memAddr, regs.get(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //by the number of ones in the first two bits of the address + regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + } + else { + int tmp = ps.memory.loadUnsigned8(memAddr); + ps.memory.store8(memAddr, regs.get(Rm) & 0xFF); + regs.set(Rm, tmp); + } } public int getSuccessor(int pc) { + //according to the ARM Architecture reference, using the pc as Rd yields an undefined + //result. Therefore, we can safely assume that this instruction never equals a branch return pc + 4; } } @@ -740,10 +906,18 @@ } else { //pre-indexing, forward reading //no need to adjust the start address - } } int nextAddress = startAddress; + + OperatingMode previousMode = ps.registers.getOperatingMode(); + + //if we should transfer the user mode registers... + if (forceUser) { + //... then change the current register map, but do NOT change the current processor mode + ps.registers.switchOperatingMode(OperatingMode.USR); + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + } //are we supposed to load or store multiple registers? if (isLoad) { @@ -761,8 +935,22 @@ int newpc = ps.memory.load32(nextAddress); regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - //shall we switch to thumb mode - regs.setThumbMode((newpc & 0x1) != 0); + if (forceUser) { + //when we are transferring the PC with a forced-user transfer, then we also want to + //restore the CPSR from the SPSR. + //However, at the moment our register layout is different from our operating mode. + //Therefore, sync both first by switching the operating mode to user (which is what our register layout + //is anyway). + regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + regs.restoreSPSR2CPSR(); + + //there is no write-back for this instruction. + return; + } + else { + //shall we switch to thumb mode + regs.setThumbMode((newpc & 0x1) != 0); + } } } else { int nextReg = 0; @@ -780,6 +968,12 @@ } } + //restore the register layout, if we were transferring the user mode registers + if (forceUser) { + ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + ps.registers.switchOperatingMode(previousMode); + } + if (writeBack) { //write the last address we read from back to a register if (!incrementBase) { @@ -961,7 +1155,69 @@ return pc + 4; } } + + private final class MoveToStatusRegister extends + ARM_Instructions.MoveToStatusRegister implements + ARM_Instruction { + public MoveToStatusRegister(int instr) { + super(instr); + } + + public void execute() { + //this variable is going to receive the new psr, which we will set + int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + + //are we currently in a privileged mode? + boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); + + //this variable receives the psr that we're replacing + int old_psr; + + //get the currect value for old_psr + if (transferSavedPSR) { + //if the current mode does not have a SPSR, then do nothing + if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) + return; + + old_psr = regs.getSPSR(); + } + else { + old_psr = regs.getCPSR(); + } + + //create a new CPSR value according to what pieces of the CPSR we are actually required to set + if (!transferControl || !inPrivilegedMode) { + new_psr &= 0xFFFFFF00; + new_psr |= (old_psr & 0xFF); + } + + if (!transferExtension || !inPrivilegedMode) { + new_psr &= 0xFFFF00FF; + new_psr |= (old_psr & 0xFF00); + } + + if (!transferStatus || !inPrivilegedMode) { + new_psr &= 0xFF00FFFF; + new_psr |= (old_psr & 0xFF0000); + } + + if (!transferFlags) { + new_psr &= 0x00FFFFFF; + new_psr |= (old_psr & 0xFF000000); + } + + if (transferSavedPSR) + regs.setSPSR(new_psr); + else + regs.setCPSR(new_psr); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + /** Invoke a software interrupt. */ private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements ARM_Instruction { @@ -992,63 +1248,8 @@ /** Resolves the offset, which is (when post-indexing is not used) to be added to the * base address to create the final address. */ private int resolveOffset() { - int addrOffset; + int addrOffset = ResolvedOperand.resolve(regs, offset); - switch (offset.getType()) { - case Immediate: - addrOffset = offset.getImmediate(); - break; - - case Register: - addrOffset = regs.get(offset.getRegister()); - if (offset.getRegister() == ARM_Registers.PC) { - addrOffset += 8; - } - break; - - case ImmediateShiftedRegister: - addrOffset = regs.get(offset.getRegister()); - - if (offset.getRegister() == 15) - addrOffset += 8; - - switch (offset.getShiftType()) { - case ASR: - addrOffset = addrOffset >> offset.getShiftAmount(); - break; - - case LSL: - addrOffset = addrOffset << offset.getShiftAmount(); - break; - - case LSR: - addrOffset = addrOffset >>> offset.getShiftAmount(); - break; - - case ROR: - addrOffset = Integer.rotateRight(addrOffset, offset.getShiftAmount()); - break; - - case RRE: - if (regs.isCarrySet()) - addrOffset = (addrOffset >> 1) | 0x80000000; - else - addrOffset = addrOffset >> 1; - break; - - default: - throw new RuntimeException("Unexpected shift type: " - + offset.getShiftType()); - } - break; - - case PcRelative: - case RegisterShiftedRegister: - default: - throw new RuntimeException("Unexpected operand type: " - + offset.getType()); - } - if (positiveOffset) return addrOffset; else @@ -1073,11 +1274,12 @@ } public void execute() { - //should we simulate a user-mode memory access? + //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch + //to user mode. + OperatingMode previousMode = null; if (forceUserMode) { - //TODO: Implement user mode memory access - throw new RuntimeException( - "Forced user mode memory access is not yet supported."); + previousMode = ps.registers.getOperatingMode(); + ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); } //get the address of the memory, that we're supposed access @@ -1088,11 +1290,12 @@ int value; switch (size) { - case Byte: - if (signExtend) - value = ps.memory.loadSigned8(address); - else - value = ps.memory.loadUnsigned8(address); + + case Word: + value = ps.memory.load32(address); + + //according to the ARM reference, the last two bits cause the value to be right-rotated + value = Integer.rotateRight(value, (address & 0x3) * 8); break; case HalfWord: @@ -1102,8 +1305,11 @@ value = ps.memory.loadUnsigned16(address); break; - case Word: - value = ps.memory.load32(address); + case Byte: + if (signExtend) + value = ps.memory.loadSigned8(address); + else + value = ps.memory.loadUnsigned8(address); break; default: @@ -1112,27 +1318,33 @@ //finally, write the variable into a register regs.set(Rd, value); - } else { + } + else { //we are store a value from a register to memory. int value = regs.get(Rd); switch (size) { - case Byte: - ps.memory.store8(address, value); + case Word: + ps.memory.store32(address & 0xFFFFFFFE, value); break; - + case HalfWord: - ps.memory.store16(address, value); + ps.memory.store16(address, value & 0xFFFF); break; - - case Word: - ps.memory.store32(address, value); + + case Byte: + ps.memory.store8(address, value & 0xFF); break; default: throw new RuntimeException("Unexpected memory size: " + size); } } + + //if we were writing in user mode, then switch back to our previous operating mode + if (forceUserMode) { + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + } //should the memory address, which we accessed, be written back into a register? //This is used for continuous memory accesses @@ -1160,14 +1372,11 @@ * is executed. */ private final class UndefinedInstruction implements ARM_Instruction { - private final int instruction; - public UndefinedInstruction(int instr) { - this.instruction = instr; } public void execute() { - throw new RuntimeException("Undefined instruction: " + instruction); + ps.doUndefinedInstruction(); } public int getSuccessor(int pc) { @@ -1235,7 +1444,6 @@ return new DataProcessing_Teq(instr); case TST: return new DataProcessing_Tst(instr); - case CLZ: return new DataProcessing_Clz(instr); @@ -1283,6 +1491,7 @@ } public ARM_Instruction createLongMultiply(int instr) { + //TODO: Implement multiplications with longs throw new RuntimeException("Long Multiplications are not yet supported."); } @@ -1291,9 +1500,7 @@ } public ARM_Instruction createMoveToStatusRegister(int instr) { - //TODO: Implement Register -> CPSR transfers - throw new RuntimeException( - "Modifying the status register using MSR is not yet supported."); + return new MoveToStatusRegister(instr); } public ARM_Instruction createSingleDataTransfer(int instr) { Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-26 20:27:47 UTC (rev 94) @@ -6,8 +6,7 @@ public class ARM_LinuxSystemCalls extends LinuxSystemCalls { - private final ARM_LinuxProcessSpace ps; - + public ARM_LinuxSystemCalls(ARM_LinuxProcessSpace ps, LinuxSystemCallGenerator src) { super(src); @@ -25,6 +24,7 @@ systemCallTable[91] = new LinuxSystemCalls.SysMunmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); + systemCallTable[195] = new LinuxSystemCalls.SysStat64(); systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); systemCallTable[199] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[200] = new LinuxSystemCalls.SysGetEGID(); @@ -32,8 +32,7 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - - this.ps = ps; + } @Override Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-26 20:27:47 UTC (rev 94) @@ -167,7 +167,7 @@ previousInputLine = new BufferedReader(new InputStreamReader(System.in)).readLine(); //don't forget the Angel expects us to submit a carriage return etc. too - previousInputLine += "\n\r"; + previousInputLine += "\n"; } if (DBT.VerifyAssertions) DBT._assert(previousInputLine != null); @@ -344,7 +344,10 @@ char output = (char)ps.memory.loadUnsigned8(ptrOutput++); while (output != 0) { - consoleOutput.print(output); + + if (output != 13) + consoleOutput.print(output); + output = (char)ps.memory.loadUnsigned8(ptrOutput++); } } @@ -428,6 +431,10 @@ try { int value = consoleInput.read(); + //skip #13, because that's what Angel seems to do. + while (value == 13) + value = consoleInput.read(); + if (value == -1) throw new RuntimeException("Unable to read further characters from console"); Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -111,4 +111,15 @@ public String toString() { return registers.toString(); } + + /** + * ARM undefined instruction handler. This method is called when the ARM processor + * is asked to execute an undefined instruction. By default, this throws a runtime exception. + * + * However, derived classes may re-implement this behaviour to achieve full system emulation. + * + */ + public void doUndefinedInstruction() { + throw new RuntimeException("Undefined instruction at 0x" + Integer.toHexString(getCurrentInstructionAddress())); + } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-26 20:27:47 UTC (rev 94) @@ -58,13 +58,13 @@ * This flag from the CPSR denotes whether IRQs are currently accepted by the * processor. */ - private boolean flagIRQsDisabled = false; + private boolean flagIRQsDisabled = true; /** * This flag from the CPSR denotes whether FIQs are currently accepted by the * processor. */ - private boolean flagFIQsDisabled = false; + private boolean flagFIQsDisabled = true; /** * The operating mode from the CPSR register. Note that only the bottom five @@ -119,18 +119,63 @@ regs[reg] = value; } - public void switchOperatingMode(OperatingMode newMode) { + /** + * Switches the current processor operating mode to <code>newMode</code>, by loading the appropriate + * register layout for the mode and changing the processor's OperatingMode flag. + * During this process, the SPSR of the newMode is replaced with the CPSR of the current mode. + * + * @param newMode + * The operating mode that shall switch to. + */ + public void switchOperatingModeAndStoreSPSR(OperatingMode newMode) { + //get the previous SPSR int previous_cpsr = getCPSR(); + //change the current operating mode + switchOperatingMode(newMode); + + setSPSR(previous_cpsr); + } + + /** + * Sets the current operating mode and loads the register layout for that mode. + * However, the CPSR is not pushed into the new mode's SPSR. + * + * @param newMode + * The operating mode to switch to. + */ + public void switchOperatingMode(OperatingMode newMode) { + //perform the actual mode switch + setRegisterLayout(newMode); + operatingMode = newMode; + } + + /** + * Sets the processor's operating mode without changing the register layout. + * This is useful in certain situations, where a command just "fakes" to be in another mode + * so that the memory is fooled. + * + * @param newMode + */ + public void setOperatingModeWithoutRegisterLayout(OperatingMode newMode) { + operatingMode = newMode; + } + + /** + * Sets the layout of the ARM registers to the layout expected in <code>newMode</code>. + * + * @param newMode + * The mode for which the register layout shall be constructed. + */ + private void setRegisterLayout(OperatingMode newMode) { + //if we're either not switching to a new mode or if we're switching between SYS and USR mode, then //take a special fast-path if (newMode == operatingMode || ((operatingMode == OperatingMode.USR || newMode == OperatingMode.SYS) && (operatingMode == OperatingMode.SYS || newMode == OperatingMode.USR))) { - //we don't need to do anything in this case, except for copying the CPSR to the SPSR - operatingMode = newMode; - setSPSR(previous_cpsr); + //we don't need to do anything in this case return; } @@ -196,7 +241,7 @@ regs[11] = shadowRegisters[shadowOffset++]; regs[12] = shadowRegisters[shadowOffset++]; } - else if (operatingMode == OperatingMode.USR) { + else if (newMode == OperatingMode.USR) { //skip these shadow registers for now shadowOffset += 5; } @@ -204,14 +249,30 @@ //now load the remaining r13 and r14 registers regs[13] = shadowRegisters[shadowOffset++]; regs[14] = shadowRegisters[shadowOffset]; + } + + /** + * Overwrites the SPSR of the current mode with the supplied value. + * + * @param newSPSR + * The new value, which will replace the current SPSR. + */ + public void setSPSR(int newSPSR) { + //save the previous CPSR as the current SPSR + if (operatingMode == OperatingMode.USR || operatingMode == OperatingMode.SYS) { + //these modes don't have a SPSR, so ignore them + return; + } - //perform the actual mode switch - operatingMode = newMode; - - //save the previous CPSR as the current SPSR - setSPSR(previous_cpsr); + shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET] = newSPSR; } + /** + * Returns the current operating mode. + */ + public OperatingMode getOperatingMode() { + return operatingMode; + } /** * Restores the saved program status register of the current operating mode to the CPSR, @@ -220,8 +281,18 @@ public void restoreSPSR2CPSR() { if (VM.VerifyAssertions) VM._assert(operatingMode != OperatingMode.USR); - setFlagsFromCPSR(getSPSR()); + setCPSR(getSPSR()); } + + /** + * Used to control the processor flag which says if the the processor is accepting interrupt requests. + * + * @param enabled + * Set to true to enable interrupts or false otherwise. + */ + public void setInterruptsEnabled(boolean enabled) { + flagIRQsDisabled = !enabled; + } /** * Returns the content of ARM's Current Program Status Register. @@ -246,20 +317,6 @@ return shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET]; } - - /** - * Set's the current mode's Saved Program status register. - * @param newSPSR - */ - public void setSPSR(int newSPSR) { - - if (operatingMode == OperatingMode.USR || operatingMode == OperatingMode.SYS) { - //these modes don't have a SPSR, so ignore them - return; - } - - shadowRegisters[operatingMode.SHADOW_OFFSET + SPSR_OFFSET] = newSPSR; - } /** * Restores the processor state to the state saved within the given CPSR. @@ -267,9 +324,9 @@ * @param cpsr * ARM CPSR register content */ - public void setFlagsFromCPSR(int cpsr) { + public void setCPSR(int cpsr) { - //extract teh differnet flags from the PSR + //extract the different flags from the PSR flagNegative = (cpsr & 0x80000000) != 0; //bit 31 flagZero = (cpsr & 0x40000000) != 0; //bit 30 flagCarry = (cpsr & 0x20000000) != 0; //bit 29 @@ -285,6 +342,7 @@ for (OperatingMode opMode : OperatingMode.values()) if (opMode.PSR_IDENTIFIER == mode) { switchOperatingMode(opMode); + break; } if (DBT.VerifyAssertions) DBT._assert(operatingMode.PSR_IDENTIFIER == mode); Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -53,11 +53,37 @@ setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); } else { - throw new RuntimeException("Non-Angel system calls are not yet supported."); + //switch the operating mode to Supervisor + registers.switchOperatingModeAndStoreSPSR(ARM_Registers.OperatingMode.SVC); + registers.setInterruptsEnabled(false); + + //put the return address into the link register + registers.set(ARM_Registers.LR, getCurrentInstructionAddress() + 4); + + //jump to the respective SWI handler + setCurrentInstructionAddress(0x8); } } + /** + * This implementation of the undefined instruction handler behaves as + * the ARM processor would: It switches the operating mode, + * jumps to the undefined instruction handler and tries to execute the instruction + * stored there. + */ @Override + public void doUndefinedInstruction() { + registers.switchOperatingModeAndStoreSPSR(ARM_Registers.OperatingMode.SVC); + registers.setInterruptsEnabled(false); + + //put the return address into the link register + registers.set(ARM_Registers.LR, getCurrentInstructionAddress() + 4); + + //jump to the respective SWI handler + setCurrentInstructionAddress(0x4); + } + + @Override public GdbTarget getGdbTarget() { throw new UnsupportedOperationException("GDB not implemented."); } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-26 20:27:47 UTC (rev 94) @@ -71,6 +71,24 @@ registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } + @Override + protected String[] getEnvironmentVariables() { + return new String[] { "PWD=/root", + "PS1=\\h:\\w\\$", + "USER=root", + "MAIL=/var/mail/root", + "LANG=C", + "SSH_CLIENT=130.88.199.8 54342 22", + "LOGNAME=root", + "SHLVL=1", + "SHELL=/bin/bash", + "HOME=/root", + "TERM=xterm", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11", + "SSH_TTY=/dev/pts/1", + "_=/usr/bin/env" }; + } + public void dumpStack() { //grab the current frame pointer int fp = registers.get(ARM_Registers.FP); Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-26 20:27:47 UTC (rev 94) @@ -68,13 +68,11 @@ } public void setSysCallError(int r) { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, -r); } public void setSysCallReturn(int r) { - // TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, r); } /** An argument iterator that hides the layout of syscall arguments on the ARM architecture */ Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-26 20:27:47 UTC (rev 94) @@ -84,8 +84,7 @@ } public void setSysCallError(int r) { -// TODO Auto-generated method stub - throw new RuntimeException("Not yet implemented."); + ps.registers.set(0, -r); } public void setSysCallReturn(int value) { Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-26 20:27:47 UTC (rev 94) @@ -18,10 +18,10 @@ while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); - System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); - pc = instruction.getSuccessor(pc); + //System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); + pc = instruction.getSuccessor(pc); if (pc == -1) pc = ps.getCurrentInstructionAddress(); Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-04-26 20:27:47 UTC (rev 94) @@ -60,8 +60,8 @@ return mem.load32(addr); } catch (Exception e) { - ensureMapped(addr, addr + 4); - return load32(addr); + mem.ensureMapped(addr, addr + 4); + return mem.load32(addr); } } @@ -70,8 +70,8 @@ return mem.loadInstruction32(addr); } catch (Exception e) { - ensureMapped(addr, addr + 4); - return loadInstruction32(addr); + mem.ensureMapped(addr, addr + 4); + return mem.loadInstruction32(addr); } } @@ -80,7 +80,7 @@ return mem.loadInstruction8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadInstruction8(addr); } } @@ -90,7 +90,7 @@ return mem.loadSigned16(addr); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); return mem.loadSigned16(addr); } } @@ -100,7 +100,7 @@ return mem.loadSigned8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadSigned8(addr); } } @@ -110,7 +110,7 @@ return mem.loadUnsigned16(addr); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); return mem.loadUnsigned16(addr); } } @@ -120,7 +120,7 @@ return mem.loadUnsigned8(addr); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); return mem.loadUnsigned8(addr); } } @@ -138,7 +138,7 @@ mem.store16(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 2); + mem.ensureMapped(addr, addr + 2); mem.store16(addr, value); } } @@ -148,7 +148,7 @@ mem.store32(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 4); + mem.ensureMapped(addr, addr + 4); mem.store32(addr, value); } } @@ -158,7 +158,7 @@ mem.store8(addr, value); } catch (Exception e) { - ensureMapped(addr, addr + 1); + mem.ensureMapped(addr, addr + 1); mem.store8(addr, value); } } Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-26 20:27:47 UTC (rev 94) @@ -11,7 +11,6 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; -import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.compilers.opt.ir.OPT_Operand; @@ -79,6 +78,22 @@ private static final int getPTE(int address) { return address >>> OFFSET_BITS; } + + /** + * Ensure memory between start and end is mapped + * @param startAddr starting address for mapped memory + * @param endAddr ending address for mapped memory + */ + @Override + public void ensureMapped(int startAddr, int endAddr) throws MemoryMapException { + startAddr = truncateToPage(startAddr); + endAddr = truncateToNextPage(endAddr); + for (;startAddr < endAddr; startAddr += getPageSize()) { + if (!isMapped(startAddr)) { + map(startAddr, getPageSize(), true, true, true); + } + } + } /** * Find free consecutive pages @@ -120,11 +135,16 @@ * is the page writable * @param exec * is the page executable + * @return + * The start address of the mapped memory. */ public int map(int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException { // Check that the address is page aligned if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + + /* // if it is not, truncate the address down to the next page boundary and // start mapping from there int validPageCount = addr / PAGE_SIZE; @@ -135,7 +155,7 @@ DBT._assert(oldStartAddress > addr); // we have to map more more memory now to reach the same end address - len += (oldStartAddress - addr); + len += (oldStartAddress - addr);*/ } // Create memory @@ -196,12 +216,6 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } - // Check file offset is page aligned - /* - if ((offset % PAGE_SIZE) != 0) { - MemoryMapException.unalignedFileOffset(offset); - } - */ // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; @@ -257,31 +271,25 @@ throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } - // Allocate page - if (read && write) { - readableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - writableMemory[pte + i] = readableMemory[pte + i]; - if (exec) { - executableMemory[pte + i] = readableMemory[pte + i]; - } - } else if (read) { - readableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - if (exec) { - executableMemory[pte + i] = readableMemory[pte + i]; - } - } else if (exec) { - executableMemory[pte + i] = file.getChannel().map( - FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), - PAGE_SIZE).array(); - } else { - throw new Error("Unable to map address 0x" - + Integer.toHexString(addr) + " with permissions " - + (read ? "r" : "-") + (write ? "w" : "-") + (exec ? "x" : "-")); + + byte[] page; + + if (write) + page = file.getChannel().map(FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); + else + page = file.getChannel().map(FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); + + if (write) { + writableMemory[pte + i] = page; } + + if (read) { + readableMemory[pte + 1] = page; + } + + if (exec) { + executableMemory[pte + i] = page; + } } } return addr; Modified: src/org/binarytranslator/generic/memory/MemoryMapException.java =================================================================== --- src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-26 20:26:01 UTC (rev 93) +++ src/org/binarytranslator/generic/memory/MemoryMapException.java 2007-04-26 20:27:47 UTC (rev 94) @@ -13,21 +13,20 @@ /** * Captures exceptions that can occur during memory mangement */ -final public class MemoryMapException extends RuntimeException { - /** - * Attempt to allocate on a non-page boundary - */ - private static final int UNALIGNED_ADDRESS = 1; +final public class MemoryMapException + extends RuntimeException { + + public enum Reason { + /** Attempt to allocate on a non-page boundary */ + UNALIGNED_ADDRESS, + /** Attempt to allocate from a file on an unaligned file offset */ + UNALIGNED_FILE_OFFSET + } /** - * Attempt to allocate from a file on an unaligned file offset - */ - private static final int UNALIGNED_FILE_OFFSET = 2; - - /** * The type of this memory map exception */ - private int type; + private Reason reason; /** * The file offset or address that was unaligned @@ -38,36 +37,37 @@ * Throw an unaligned address memory map exception */ static void unalignedAddress(int addr) throws MemoryMapException { - throw new MemoryMapException((long) addr, UNALIGNED_ADDRESS); + throw new MemoryMapException((long) addr, Reason.UNALIGNED_ADDRESS); } /** * Throw an unaligned file offset memory map exception */ static void unalignedFileOffset(long offset) throws MemoryMapException { - throw new MemoryMapException(offset, UNALIGNED_FILE_OFFSET); + throw new MemoryMapException(offset, Reason.UNALIGNED_FILE_OFFSET); } /** * Constructor */ - private MemoryMapException(long addr, int type) { + private MemoryMapException(long addr, Reason reason) { offsetOrAddress = addr; - this.type = type; + this.reason = reason; } /** * String representation of exception */ public String toString() { - switch (type) { + switch (reason) { case UNALIGNED_ADDRESS: - return "Unaligned memory map address: 0x" - + Integer.toHexString((int) offsetOrAddress); + return String.format("Unaligned memory map address: 0x%x", offsetOrAddress); + case UNALIGNED_FILE_OFFSET: - return "Unaligned file offset: " + offsetOrAddress; + return String.format("Unaligned file offset: 0x%x", offsetOrAddress); + + default: + throw new RuntimeException("Unexpected MemoryMapException Reason: " + reason); } - DBT_OptimizingCompilerException.UNREACHABLE(); - return null; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-28 16:18:58
|
Revision: 96 http://svn.sourceforge.net/pearcolator/?rev=96&view=rev Author: michael_baer Date: 2007-04-28 09:18:58 -0700 (Sat, 28 Apr 2007) Log Message: ----------- - Moved setBrk() / getBrk() to LinuxSystemCalls Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -1,6 +1,5 @@ package org.binarytranslator.arch.arm.os.process.linux; -import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.abi.linux.ARM_LinuxSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; @@ -10,7 +9,6 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.generic.os.loader.elf.ELF_Loader; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace { @@ -33,7 +31,7 @@ private int[] auxVector; public ARM_LinuxProcessSpace() { - sysCallGenerator = new Legacy(this, 0xEBADADD); + sysCallGenerator = new Legacy(this); sysCalls = new ARM_LinuxSystemCalls(this, sysCallGenerator); } @@ -49,7 +47,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { registers.set(ARM_Registers.PC, pc); - sysCallGenerator.setBrk(brk); + sysCalls.initialize(brk); // initialize the stack auxVector = new int[] { Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/EABI.java 2007-04-28 16:18:58 UTC (rev 96) @@ -1,7 +1,6 @@ package org.binarytranslator.arch.arm.os.process.linux.abi; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -29,18 +28,12 @@ /** The process space that we're running on. */ private final ARM_LinuxProcessSpace ps; private final ArgumentIterator args; - private int brk; - public EABI(ARM_LinuxProcessSpace ps, int brk) { + public EABI(ARM_LinuxProcessSpace ps) { this.ps = ps; - this.brk = brk; this.args = new ArgumentIterator(); } - public int getBrk() { - return brk; - } - public ProcessSpace getProcessSpace() { return ps; } @@ -54,19 +47,6 @@ return ps.registers.get(7); } - public void setBrk(int address) { - - try { - ps.memory.ensureMapped(brk, address); - } catch (MemoryMapException e) { - throw new Error(String.format( - "Error changing top of BSS from 0x%x to address 0x%x", brk, address), - e); - } - - brk = address; - } - public void setSysCallError(int r) { ps.registers.set(0, -r); } Modified: src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java 2007-04-28 16:18:58 UTC (rev 96) @@ -4,7 +4,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -32,30 +31,11 @@ * system call */ private final ArgumentIterator syscallArgs; - private int brk; - - - public Legacy(ARM_LinuxProcessSpace ps, int brk) { + public Legacy(ARM_LinuxProcessSpace ps) { this.ps = ps; - this.brk = brk; syscallArgs = new ArgumentIterator(); } - public int getBrk() { - return brk; - } - - public void setBrk(int address) { - try { - ps.memory.ensureMapped(brk, address); - } catch (MemoryMapException e) { - throw new Error("Error changing top of BSS to address 0x"+Integer.toHexString(address)+ - " from 0x" + Integer.toHexString(brk), e); - } - - brk = address; - } - public ProcessSpace getProcessSpace() { return ps; } Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -40,11 +40,6 @@ final PPC_LinuxSyscallArgumentIterator syscallArgs; /** - * The top of the bss segment - */ - private int brk; - - /** * The top of the stack */ private static final int STACK_TOP = 0x80000000; @@ -74,8 +69,8 @@ */ public void initialise(Loader loader, int pc, int brk) { this.pc = pc; - this.brk = brk; this.r1 = initialiseStack(loader, pc); + syscalls.initialize(brk); } /** @@ -178,27 +173,6 @@ setCR_bit(0, true); } - /** - * Get the top of the BSS segment (the heap that reside below the stack in - * memory) - * - * @return top of BSS segment - */ - public int getBrk() { - return brk; - } - - /** - * Set the top of the BSS segment (the heap that reside below the stack in - * memory) - * - * @param address - * new top of BSS segment - */ - public void setBrk(int address) { - brk = address; - } - public GdbTarget getGdbTarget() { return this; } Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-28 16:18:58 UTC (rev 96) @@ -40,11 +40,6 @@ private final X86_LinuxSyscallArgumentIterator syscallArgs; /** - * The top of the bss segment - */ - private int brk; - - /** * The top of the stack */ private static final int STACK_TOP = 0xC0000000; @@ -71,7 +66,7 @@ */ public void initialise(Loader loader, int pc, int brk) { registers.eip = pc; - this.brk = brk; + registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); if (useSysInfoPage) { try { @@ -83,6 +78,8 @@ memory.store8(0xffffe400, 0x80); // 80h memory.store8(0xffffe400, 0xC3); // RET } + + syscalls.initialize(brk); } /** @@ -146,29 +143,6 @@ registers.writeGP32(X86_Registers.EAX, -r); } - /** - * Get the top of the BSS segment (the heap that reside below the - * stack in memory) - * @return top of BSS segment - */ - public int getBrk() { - return brk; - } - /** - * Set the top of the BSS segment (the heap that reside below the - * stack in memory) - * @param address new top of BSS segment - */ - public void setBrk(int address) { - try { - memory.ensureMapped(brk, address); - } catch (MemoryMapException e) { - throw new Error("Error changing top of BSS to address 0x"+Integer.toHexString(address)+ - " from 0x" + Integer.toHexString(brk), e); - } - brk = address; - } - public void setStackPtr(int ptr) {} public int[] getAuxVector() { Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCallGenerator.java 2007-04-28 16:18:58 UTC (rev 96) @@ -8,7 +8,6 @@ */ package org.binarytranslator.generic.os.abi.linux; -import org.binarytranslator.generic.memory.MemoryMapException; import org.binarytranslator.generic.os.process.ProcessSpace; /** @@ -52,27 +51,7 @@ * @param r the error value */ public void setSysCallError(int r); - /** - * Write to the memory of the system call generator a 32bit value - * @param address where to write - * @param data value to store - */ - - /** - * Returns the process space that this call originated from. - */ + + /** Returns the process space that this call originated from.*/ public ProcessSpace getProcessSpace(); - - /** - * Get the top of the BSS segment (the heap that reside below the - * stack in memory) - * @return top of BSS segment - */ - public int getBrk(); - /** - * Set the top of the BSS segment (the heap that reside below the - * stack in memory) - * @param address new top of BSS segment - */ - public void setBrk(int address); } Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-27 15:03:23 UTC (rev 95) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-28 16:18:58 UTC (rev 96) @@ -44,12 +44,15 @@ protected LinuxStructureFactory structures; /** List of currently opened files. */ - private OpenFileList openFiles; + protected OpenFileList openFiles; + + /** The top of the bss segment */ + protected int brk; /** * Maximum number of system calls */ - private static final int MAX_SYSCALLS = 294; + protected static final int MAX_SYSCALLS = 294; /** * Array to de-multiplex Linux system calls. NB we will have to @@ -89,7 +92,7 @@ * @param address where to read * @return the String read */ - private String memoryReadString(int address) { + protected String memoryReadString(int address) { Memory m = src.getProcessSpace().memory; StringBuffer str = new StringBuffer(); @@ -106,7 +109,7 @@ * @param address where to read * @param data the String to write */ - public void memoryWriteString(int address, String data) { + protected void memoryWriteString(int address, String data) { Memory m = src.getProcessSpace().memory; if (data != null) { @@ -117,6 +120,17 @@ m.store8(address + data.length(), (byte) 0); } } + + /** + * Sets up the linux operating space + * + * @param brk + * the initial value for the top of BSS + */ + public void initialize(int brk) { + LinuxSystemCalls.this.brk = brk; + src.getProcessSpace().memory.ensureMapped(brk, brk+1); + } /** * Constructor @@ -397,12 +411,14 @@ public class SysBrk extends SystemCall { public void doSysCall() { - int brk = arguments.nextInt(); - if (brk != 0) { + int newBrk = arguments.nextInt(); + if (newBrk != 0) { // Request to set the current top of bss. - src.setBrk(brk); + brk = newBrk; + src.getProcessSpace().memory.ensureMapped(brk, brk+1); } - src.setSysCallReturn(src.getBrk()); + + src.setSysCallReturn(brk); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-15 21:59:10
|
Revision: 115 http://svn.sourceforge.net/pearcolator/?rev=115&view=rev Author: michael_baer Date: 2007-05-15 14:58:53 -0700 (Tue, 15 May 2007) Log Message: ----------- Added more flexible support for file system emulation Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -3,6 +3,7 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; public class ARM_LinuxSystemCalls extends LinuxSystemCalls { @@ -32,12 +33,10 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - } @Override public void doSysCall() { - super.doSysCall(); } @@ -46,6 +45,12 @@ //TODO: Grab this from a real machine return "ARM"; } + + @Override + protected FileProvider buildFileSystem() { + ARM_ProcFileSystem fs = new ARM_ProcFileSystem(super.buildFileSystem()); + return fs; + } @Override public String sysCallToString(int syscall) { Added: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,29 @@ +package org.binarytranslator.arch.arm.os.abi.linux; + +import org.binarytranslator.generic.os.abi.linux.files.FixedContentFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.ProcFileSystem; + +public class ARM_ProcFileSystem extends ProcFileSystem { + + public ARM_ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected ReadableFile openCpuInfo() { + + String output = ""; + output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; + output += "BogoMIPS : 599.65\n"; + output += "Features : swp half thumb fastmult edsp\n"; + output += "\n"; + output += "Hardware : Iyonix\n"; + output += "Revision : 0000\n"; + output += "Serial : 0000000000000000\n"; + + return new FixedContentFile(output); + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -8,6 +8,7 @@ */ package org.binarytranslator.generic.os.abi.linux; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; @@ -19,6 +20,11 @@ import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; import org.binarytranslator.generic.os.abi.linux.files.WriteableFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFileList.InvalidFileDescriptor; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.HostFileSystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.ReadonlyFilesystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.TempFileSystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider.FileMode; import org.binarytranslator.generic.os.abi.linux.LinuxConstants.*; import java.io.File; @@ -46,6 +52,9 @@ /** List of currently opened files. */ protected OpenFileList openFiles; + /** List of currently opened files. */ + protected FileProvider filesystem; + /** The top of the bss segment */ protected int brk; @@ -144,16 +153,32 @@ openFiles = new OpenFileList(); - if (openFiles.open(new ConsoleIn(), 0) != 0 - || openFiles.open(new ConsoleOut(System.out), 1) != 1 - || openFiles.open(new ConsoleOut(System.err), 2) != 2) { + if (openFiles.add(new ConsoleIn(), 0) != 0 + || openFiles.add(new ConsoleOut(System.out), 1) != 1 + || openFiles.add(new ConsoleOut(System.err), 2) != 2) { throw new RuntimeException( "File descriptors for standard streams could not be assigned correctly."); } structures = new LinuxStructureFactory(); + filesystem = buildFileSystem(); } + + /** + * This method creates a virtual file system for this linux host. Override it, to create a specific file systems + * for an architecture. + * + * The standard implementation mounts the host's file system readonly but enables writes to the host's temp directory. + * @return + * A {@link FileProvider} that will be used to access the file system for this host. + */ + protected FileProvider buildFileSystem() { + FileProvider fs = new HostFileSystem(null); + fs = new ReadonlyFilesystem(fs); + fs = new TempFileSystem(fs); + return fs; + } /** * Handle a system call @@ -318,42 +343,51 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. String fileName = memoryReadString(pathname); + + FileMode mode; - // Create a File object so we can test for the existance and - // properties of the file. - File testFile = new File(fileName); - - if (((flags & fcntl.O_CREAT) != 0) && ((flags & fcntl.O_EXCL) != 0) - && testFile.exists()) { - // O_CREAT specified. If O_EXCL also specified, we require - // that the file does not already exist - src.setSysCallError(errno.EEXIST); - return; - } else if (((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { - // O_CREAT not specified. We require that the file exists. - src.setSysCallError(errno.ENOENT); - return; + //shall we create the target file? + if ((flags & fcntl.O_CREAT) != 0) { + //We want to create a file. This also implies that we're gonna write to it + mode = FileMode.WriteCreate; + if (DBT.VerifyAssertions) DBT._assert((flags & 0x3) != fcntl.O_RDONLY); + + //Yes, we want to create that file. Do we demand that it does not yet exist? + if ((flags & fcntl.O_EXCL) != 0) { + //check if it does not exist by trying to open it + OpenFile testfile = filesystem.openFile(fileName, FileMode.Read); + + if (testfile != null) { + //the file we're trying to create already exists. With O_EXCL, this is an error condition. + src.setSysCallError(errno.EEXIST); + try { + testfile.close(); + } catch (IOException e) {} + + return; + } + } } - - // we have not found an error, so we go ahead and try to open the file - try { - RandomAccessFile raFile; - int fd; - - if ((flags & 0x3) == fcntl.O_RDONLY) { - raFile = new RandomAccessFile(fileName, "r"); - fd = openFiles.open(HostFile.forReading(raFile)); - } else { - // NB Java RandomAccessFile has no write only - raFile = new RandomAccessFile(fileName, "rw"); - fd = openFiles.open(HostFile.forWriting(raFile)); - } - src.setSysCallReturn(fd); - } catch (FileNotFoundException e) { - System.err.println("Open tried to open non-existent file: " + fileName); + else { + //we shall not create the file. Check if we're supposed to open it for reading, though + if ((flags & 0x3) == fcntl.O_RDONLY) + mode = FileMode.Read; + else + mode = FileMode.Write; + } + + OpenFile file = filesystem.openFile(fileName, mode); + + //did we successfully open the file? + if (file == null) { + //if not, return with an error src.setSysCallError(errno.ENOENT); return; } + + //otherwise add it to the list of open files and return a handle to the file + int fd = openFiles.add(file); + src.setSysCallReturn(fd); // NOT YET HANDLING ALL THE flags OPTIONS (IW have included // TRUNC & APPEND but not properly!) Added: src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,51 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; + +/** + * This is a file, for which the content is given by a constant string or byte array. + */ +public class FixedContentFile implements ReadableFile { + + /** The data that is actually returned to a reader. */ + protected final byte[] data; + + /** An integer offset into the {@link #data} array, that points at the next byte that is to be read. */ + protected int readPtr; + + public FixedContentFile(byte[] data) { + readPtr = 0; + this.data = data; + } + + public FixedContentFile(String asciiData) { + readPtr = 0; + data = new byte[asciiData.length()]; + + for (int i = 0; i < asciiData.length(); i++) + data[i] = (byte)asciiData.charAt(i); + } + + public int read(byte[] buffer) throws IOException { + + if (readPtr == data.length) { + return -1; + } + + for (int i = 0; i < buffer.length; i++) { + + if (readPtr == data.length) { + return i; + } + + buffer[i] = data[readPtr++]; + } + + return buffer.length; + } + + public void close() throws IOException { + //no-op + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-15 21:58:53 UTC (rev 115) @@ -27,7 +27,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file) { + public int add(OpenFile file) { int handle = nextFileHandle++; files.put(nextFileHandle, file); @@ -47,7 +47,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file, int preferredFd) { + public int add(OpenFile file, int preferredFd) { if (files.get(preferredFd) != null) { preferredFd = nextFileHandle++; } Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,34 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * This is a base class for file system that follow the chain of responsibility pattern. + * In this pattern, all file systems are chained and if one file system cannot handle the request to + * open a specific file, the request is forwarded to the next file system until either one system + * can provide the file or the end of the chain is reached. + * + */ +public abstract class ChainedFileProvider implements FileProvider { + + protected final FileProvider nextProvider; + + public ChainedFileProvider(FileProvider nextProvider) { + + if (nextProvider == null) + nextProvider = new NullFileSystem(); + + this.nextProvider = nextProvider; + } + + public OpenFile openFile(String file, FileMode mode) { + OpenFile result = tryOpen(file, mode); + + if (result == null) + result = nextProvider.openFile(file, mode); + + return result; + } + + protected abstract OpenFile tryOpen(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,26 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * The FileProvider interface defines the methods that any class shall implement, that serves as (part) + * of the virtual file system that is simulated for the linux guest OS. */ +public interface FileProvider { + + public enum FileMode { + Read, + Write, + WriteCreate + } + + /** + * Opens the given file on the host. + * @param file + * The path of the file that is to be opened. + * @param mode + * The mode with which the file shall be opened. + * @return + * A file object representing the file on success or null otherwise. + */ + public OpenFile openFile(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,50 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.RandomAccessFile; + +import org.binarytranslator.generic.os.abi.linux.files.HostFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +public class HostFileSystem extends ChainedFileProvider { + + + public HostFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + + try { + File f = new File(file); + + if (!f.isFile()) + return null; + + switch (mode) { + case Read: + if (!f.exists()) + return null; + + return HostFile.forReading(new RandomAccessFile(f, "r")); + + case Write: + if (!f.exists()) + return null; + + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + case WriteCreate: + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + default: + throw new RuntimeException("Invalid file open mode: " + mode); + } + + } catch (FileNotFoundException e) { + return null; + } + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,15 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A NULL filesystem object. + * + */ +public class NullFileSystem implements FileProvider { + + public OpenFile openFile(String file, FileMode mode) { + //no-nop + return null; + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,32 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; + +/** Represents the Unix /proc/ file system. */ +public abstract class ProcFileSystem extends ChainedFileProvider { + + /** A string that defines the path of the virtual proc file system on the guest. */ + protected final static String PROC_DIRECTORY_PATH = "/proc/"; + + public ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(PROC_DIRECTORY_PATH)) + return null; + + if (file.equals(PROC_DIRECTORY_PATH + "cpuinfo") && mode == FileMode.Read) + return openCpuInfo(); + + return null; + } + + /** + * Called when the application tries to open /proc/cpuinfo. + * Implement it by returning a {@link ReadableFile} that contains the information usually returned by /proc/cpuinfo. + */ + protected abstract ReadableFile openCpuInfo(); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A file system decorator, that prevents all write-accesses to this file system. + */ +public final class ReadonlyFilesystem implements FileProvider { + + private final FileProvider filesystem; + + public ReadonlyFilesystem(FileProvider filesystem) { + this.filesystem = filesystem; + } + + public OpenFile openFile(String file, FileMode mode) { + if (mode != FileMode.Read) + return null; + + return filesystem.openFile(file, mode); + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** This class allows write-access to the /tmp file system from the guest. */ +public class TempFileSystem extends HostFileSystem { + + /** A string that defines the location of the tmp file system on the guest. */ + protected final static String TMP_FILE_PATH = "/tmp/"; + + public TempFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(TMP_FILE_PATH)) + return null; + + return super.tryOpen(file, mode); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-17 19:20:16
|
Revision: 121 http://svn.sourceforge.net/pearcolator/?rev=121&view=rev Author: michael_baer Date: 2007-05-17 12:20:02 -0700 (Thu, 17 May 2007) Log Message: ----------- - Fixed in the generation of ARM_Laziness instances - Added a command line option to debug the resolution of branches Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/DBT_Options.java 2007-05-17 19:20:02 UTC (rev 121) @@ -105,9 +105,9 @@ public static boolean debugInstr = true; /** - * In PPC2IR, print information about lazy resolution... + * Print information about the lazy resolution of branch addresses... */ - public final static boolean debugLazy = false; + public static boolean debugBranchResolution = true; /** * In PPC2IR, print cfg. @@ -213,6 +213,8 @@ debugInstr = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugRuntime")) { debugRuntime = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { + debugBranchResolution = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 19:20:02 UTC (rev 121) @@ -376,20 +376,6 @@ } /** - * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. - * @param block - * @param count - */ - public void printNextBlocks(OPT_BasicBlock block, int count) { - do - { - block.printExtended(); - block = block.nextBasicBlockInCodeOrder(); - } - while (block != null && count-- > 0); - } - - /** * Adds code to the current block that will rotate <code>rotatedOperand</code> by * <code>rotation</code> and stores the rotated integer into <code>result</code>. * @param result Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-05-17 19:20:02 UTC (rev 121) @@ -4,22 +4,39 @@ public class ARM_Laziness extends Laziness { + final class ARM_LazinessKey extends Key { + private final int pc; + + public int hashCode() { + return pc; + } + + public boolean equals(Object o) { + return ((o instanceof ARM_LazinessKey) && ((ARM_LazinessKey) o).pc == pc); + } + + ARM_LazinessKey(int pc) { + this.pc = pc; + } + + public String toString() { + return "0x" + Integer.toHexString(pc); + } + } + @Override public Object clone() { - // TODO Auto-generated method stub - return null; + return new ARM_Laziness(); } @Override public boolean equivalent(Laziness other) { - // TODO Auto-generated method stub - return false; + return other instanceof ARM_Laziness; } @Override public Key makeKey(int pc) { - // TODO Auto-generated method stub - return null; + return new ARM_LazinessKey(pc); } } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 19:20:02 UTC (rev 121) @@ -238,7 +238,7 @@ do { resolveGoto(); resolveIfCmp(); - } while (((unresolvedGoto.size() == 0) && (unresolvedIfCmp.size() == 0)) == false); + } while ((unresolvedGoto.size() != 0) || (unresolvedIfCmp.size() != 0)); } else { resolveGoto(); resolveIfCmp(); @@ -304,6 +304,7 @@ setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc)); } + break; } @@ -594,6 +595,10 @@ OPT_BasicBlock target = findMapping(targetPC, targetLaziness); if (target != null) { + + if (DBT_Options.debugBranchResolution) + System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); + jump = Goto.create(GOTO, target.makeJumpTarget()); getCurrentBlock().insertOut(target); } @@ -622,18 +627,17 @@ OPT_BasicBlock targetBB = resolveJumpTarget(targetPc, lazyStateAtJump); - if (DBT_Options.debugLazy) { + if (DBT_Options.debugBranchResolution) { report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } // Fix up instruction Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().deleteNormalOut(); gotoInstr.getBasicBlock().insertOut(targetBB); if (DBT.VerifyAssertions) DBT._assert(gotoInstr.getBasicBlock().getNumberOfNormalOut() == 1); - if (DBT_Options.debugLazy) { + if (DBT_Options.debugBranchResolution) { report("Properly resolving goto in block " + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); @@ -661,6 +665,7 @@ //In Single instruction mode, the target block just ends the trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); + System.out.println("Resolving branch to next block."); } targetBB = currentBlock; @@ -1332,6 +1337,22 @@ return gc.temps.makeTemp(type); } + /** + * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. + * @param block + * The basic block that shall be printed. + * @param count + * The number of blocks following <code>block</code> that shall be printed. + */ + public void printNextBlocks(OPT_BasicBlock block, int count) { + do + { + block.printExtended(); + block = block.nextBasicBlockInCodeOrder(); + } + while (block != null && count-- > 0); + } + /** Report some debug output */ protected abstract void report(String str); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-17 22:26:47
|
Revision: 122 http://svn.sourceforge.net/pearcolator/?rev=122&view=rev Author: michael_baer Date: 2007-05-17 15:26:48 -0700 (Thu, 17 May 2007) Log Message: ----------- - Added further branch profile notifications for call & return instructions - Removed registration of unresolved IfCmps for code clarity Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 22:26:48 UTC (rev 122) @@ -1660,7 +1660,7 @@ } arm2ir.getCurrentBlock().deleteNormalOut(); - arm2ir.appendGoto(pc + getOffset() + 8, lazy); + arm2ir.appendGoto(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) @@ -11703,9 +11703,9 @@ BI, !branch_if_cond_true, likely_to_fallthrough); } - if ((LK == 0) || (ppc2ir.traceContinuesAfterBranchAndLink(pc))) { + if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { // Plant branch block - ppc2ir.appendGoto(target_address, lazy); + ppc2ir.appendGoto(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11724,15 +11724,14 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendGoto(pc + 4, lazy); + ppc2ir.appendGoto(pc + 4, lazy, BranchType.DIRECT_BRANCH); return target_address; } } } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.setReturnValueResolveLazinessAndBranchToFinish((PPC_Laziness) lazy - .clone(), new OPT_IntConstantOperand(target_address)); + ppc2ir.appendGoto(target_address, lazy, BranchType.CALL); return -1; } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) @@ -11,6 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; +import org.binarytranslator.generic.branch.BranchLogic.BranchType; import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; @@ -3646,9 +3647,9 @@ translationHelper.appendInstruction(Move.create(INT_MOVE, temp, new OPT_IntConstantOperand(pc + length))); stack.writeValue(translationHelper, lazy, temp.copyRO()); + // Branch - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( - (X86_Laziness) lazy.clone(), destOp.copyRO()); + translationHelper.appendDynamicJump(destOp.copyRO(), lazy, BranchType.CALL); return -1; } @@ -3917,7 +3918,8 @@ X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { // The destination for the branch int target_address = pc + length + immediate; - // Find a pre-translated version + + OPT_BasicBlock executeBranch = translationHelper.createBlockAfterCurrent(); OPT_BasicBlock fallThrough = translationHelper.createBlockAfterCurrent(); boolean branchLikely; if (prefix2 != null) { @@ -4027,11 +4029,14 @@ .getConditionalBranchProfileOperand(false)); } translationHelper.appendInstruction(boolcmp); - translationHelper.appendIfCmp(INT_IFCMP, translationHelper - .getTempValidation(0), temp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), target_address, lazy, likelyOp); + translationHelper.appendInstruction(IfCmp.create(INT_IFCMP, translationHelper.getTempValidation(0), temp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), executeBranch.makeJumpTarget(), likelyOp)); OPT_Instruction gotoInstr = Goto.create(GOTO, fallThrough.makeJumpTarget()); translationHelper.appendInstruction(gotoInstr); + + translationHelper.setCurrentBlock(executeBranch); + translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.setCurrentBlock(fallThrough); return pc + length; } @@ -4164,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendGoto(target_address, lazy); + translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); } else { int operandSize; if (prefix3 == null) { Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-17 22:26:48 UTC (rev 122) @@ -23,6 +23,8 @@ public enum BranchType { INDIRECT_BRANCH, + DIRECT_BRANCH, + CALL, RETURN } @@ -56,12 +58,12 @@ * * @param pc * the address of the branch instruction + * @param dest + * the destination of the branch instruction * @param ret * the address that will be returned to - * @param dest - * the destination of the branch instruction */ - public void registerCall(int pc, int ret, int dest) { + public void registerCall(int pc, int dest, int ret) { ProcedureInformation procedure = procedures.get(dest); if (procedure != null) { @@ -71,6 +73,18 @@ procedures.put(dest, procedure); } } + + /** + * Register a call (branch and link) instruction + * + * @param pc + * the address of the branch instruction + * @param dest + * the destination of the branch instruction + */ + public void registerCall(int pc, int dest) { + registerCall(pc, dest, -1); + } /** * Register a branch to the link register @@ -120,6 +134,21 @@ if (DBT.VerifyAssertions) DBT._assert(type > 0 && type < BranchType.values().length); + //Some branch types require a special registration (calls and returns) + switch (BranchType.values()[type]) { + case CALL: + registerCall(origin, target); + break; + + case RETURN: + registerReturn(origin, target); + break; + + default: + break; + } + + //Perform the general branch registration, too Set<Integer> dests = branchSitesAndDestinations.get(origin); if (dests != null && dests.contains(target)) { Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 22:26:48 UTC (rev 122) @@ -176,8 +176,6 @@ /** List of unresolved Goto instructions */ private final ArrayList<UnresolvedJumpInstruction> unresolvedGoto; - /** List of unresolved IfCmp instructions */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedIfCmp; /** List of unresolved dynamic jumps */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicJumps; @@ -211,7 +209,6 @@ // Fix up stores unresolvedGoto = new ArrayList<UnresolvedJumpInstruction>(); - unresolvedIfCmp = new ArrayList<UnresolvedJumpInstruction>(); unresolvedDynamicJumps = new ArrayList<UnresolvedJumpInstruction>(); } @@ -237,16 +234,16 @@ if (DBT_Options.resolveBranchesAtOnce) { do { resolveGoto(); - resolveIfCmp(); - } while ((unresolvedGoto.size() != 0) || (unresolvedIfCmp.size() != 0)); + + } while (unresolvedGoto.size() != 0); } else { resolveGoto(); - resolveIfCmp(); + } if (!DBT_Options.resolveProceduresBeforeBranches) { resolveAllDynamicJumpTargets(); } - } while (((unresolvedGoto.size() == 0) && (unresolvedIfCmp.size() == 0) + } while (((unresolvedGoto.size() == 0) && areDynamicJumpsReadyToResolve()) == false); // Resolve unresolved dynamic jumps @@ -520,67 +517,6 @@ } /** - * Appends an IfCmp instruction to the current block that (when the condition is true) jumps - * to the address <code>targetPc</code>. The parameters for this function are mostly - * the same as for the {@link IfCmp#create(OPT_Operator, OPT_RegisterOperand, OPT_Operand, OPT_Operand, OPT_ConditionOperand, OPT_BranchOperand, OPT_BranchProfileOperand)} function. - * - * @param operator - * The HIR operator. - * @param guard - * A guard result for this call. - * @param lhs - * The left-hand-side comparision operator. - * @param rhs - * The right-hand-side comparision operator. - * @param condition - * The type of comparison that is to be executed. - * @param targetPc - * The address that the trace shall jump to, when the condition evaluates to true. - * @param targetLaziness - * The laziness at the point of jump. - * @param branchProfile - * A branch profile operand that describes how likely it is that the jump is executed. - */ - public void appendIfCmp(OPT_Operator operator, OPT_RegisterOperand guard, OPT_Operand lhs, - OPT_Operand rhs, OPT_ConditionOperand condition, int targetPc, Laziness targetLaziness, OPT_BranchProfileOperand branchProfile) { - - OPT_BasicBlock targetBlock = findMapping(targetPc, targetLaziness); - OPT_Instruction ifcmp = IfCmp.create(operator, guard, lhs, rhs, condition, null, branchProfile); - - if (targetBlock != null) { - IfCmp.setTarget(ifcmp, targetBlock.makeJumpTarget()); - getCurrentBlock().insertOut(targetBlock); - } - else { - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(ifcmp, (Laziness)targetLaziness.clone(), targetPc); - unresolvedIfCmp.add(unresolvedJump); - } - - appendInstruction(ifcmp); - } - - /** Resolve a single ifCmp instruction */ - private void resolveIfCmp() { - - if (unresolvedIfCmp.size() == 0) - return; - - //Try to find if block has now been translated - UnresolvedJumpInstruction instruction = unresolvedIfCmp.remove(unresolvedIfCmp.size() - 1); - - OPT_Instruction ifCmp = instruction.instruction; - - if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(ifCmp)); - - //try to resolve the ifcmp's jump target - OPT_BasicBlock targetBB = resolveJumpTarget(instruction.pc, instruction.lazyStateAtJump); - - //Fix up the instruction - IfCmp.setTarget(ifCmp, targetBB.makeJumpTarget()); - ifCmp.getBasicBlock().insertOut(targetBB); - } - - /** * Create a HIR Goto instruction that jumps to the address <code>targetPc</code>. There's * a caveat on using this that there are no other out edges for this BB. * @@ -588,27 +524,50 @@ * The address where we shall jump to. * @param targetLaziness * The current at the point of jump. + * @param branchType + * The type of branch that best describes this jump. */ - public void appendGoto(int targetPC, Laziness targetLaziness) { + public void appendGoto(int targetPC, Laziness targetLaziness, BranchType branchType) { - OPT_Instruction jump; + //see if we already compiled the target address OPT_BasicBlock target = findMapping(targetPC, targetLaziness); + //if yes, just jump directly to it if (target != null) { if (DBT_Options.debugBranchResolution) System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); - jump = Goto.create(GOTO, target.makeJumpTarget()); + OPT_Instruction jump = Goto.create(GOTO, target.makeJumpTarget()); getCurrentBlock().insertOut(target); + appendInstruction(jump); } else { - jump = Goto.create(GOTO, null); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); - unresolvedGoto.add(unresolvedJump); + //otherwise, we have to decide whether to compile that address into the trace or to compile + //it as a separate trace. We use the branchType hint for that... + + switch (branchType) { + case CALL: + //exit the trace on a call + ps.branchInfo.registerCall(currentPC, targetPC); + setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); + break; + + case RETURN: + //exit the trace + ps.branchInfo.registerReturn(currentPC, targetPC); + setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); + break; + + default: + //compile the jump directly into the trace. + OPT_Instruction jump = Goto.create(GOTO, null); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); + unresolvedGoto.add(unresolvedJump); + } } - appendInstruction(jump); + } /** Resolve a single goto instruction */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-21 17:43:20
|
Revision: 127 http://svn.sourceforge.net/pearcolator/?rev=127&view=rev Author: michael_baer Date: 2007-05-21 10:43:21 -0700 (Mon, 21 May 2007) Log Message: ----------- - enabled load/storing a branch profile from file - added branch profiling in ARM interpreted code when DBT_Options.profileDuringInterpration is set - slightly changed handling of branch profile creation - Using a HashMap instead of a Weakhashmap in CodeCache to prevent a VM assertion - minor fixes Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/CodeCache.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/DBT_Options.java 2007-05-21 17:43:21 UTC (rev 127) @@ -19,16 +19,15 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; - /** - * Debug binary loading - */ + /** Enable the profiling of application during interpretation? */ + public final static boolean profileDuringInterpretation = true; + + /** Debug binary loading */ public final static boolean debugLoader = true; - /** - * Are unimplemented system calls are fatal? - */ + /** Are unimplemented system calls are fatal? */ public final static boolean unimplementedSystemCallsFatal = false; // -oO Translation settings Oo- @@ -208,6 +207,8 @@ debugRuntime = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { debugBranchResolution = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugMemory")) { + debugMemory = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/Main.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.io.File; +import java.io.IOException; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; @@ -29,6 +30,8 @@ * */ public class Main { + private static ProcessSpace ps; + /** * Debug information * @@ -49,6 +52,8 @@ System.out .println("org.binarytranslator.Main [-X:dbt:...] <program> <args...>"); } + + /** * Main method @@ -81,8 +86,6 @@ return; } - ProcessSpace ps; - try { report("Loading " + DBT_Options.executableFile); Loader loader = Loader.getLoader(DBT_Options.executableFile); @@ -120,6 +123,16 @@ } controller.run(); - System.out.println("\nProgram has finished."); + System.out.println("\nExecution controller has exited."); } + + public static void onExit(int exitcode) { + System.out.println("\nProgram has finished. Exitcode: " + exitcode); + + try { + ps.branchInfo.saveAsXML("/tmp/profile.xml"); + } catch (IOException e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; @@ -8,6 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; +import org.binarytranslator.generic.branch.BranchLogic.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; @@ -457,7 +459,39 @@ } public abstract void execute(); + + /** + * Stores the result of adding <code>lhs</code> + <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setAddResult(int lhs, int rhs) { + setFlagsForAdd(lhs, rhs); + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, lhs + rhs); + } + + /** + * Stores the result of adding <code>lhs</code> - <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setSubResult(int lhs, int rhs) { + setFlagsForSub(lhs, rhs); + + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, lhs - rhs); + } + /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ protected final void setFlagsForAdd(int lhs, int rhs) { @@ -522,6 +556,21 @@ return super.resolveOperand2(); } } + + /** Stores the result of a logical operation to a register and, if <code>updateConditionFlags</code> + * is set, also sets the flags accordingly. */ + protected final void setLogicalResult(int result) { + + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (getOpcode() == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) + ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result); + else + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, result); + setFlagsForLogicalOperator(result); + } /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { @@ -546,8 +595,7 @@ @Override public void execute() { int result = resolveOperand1() & resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -561,8 +609,7 @@ @Override public void execute() { int result = resolveOperand1() ^ resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -576,10 +623,8 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -594,10 +639,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -612,10 +654,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand2 - operand1; - - regs.set(Rd, result); - setFlagsForSub(operand2, operand1); + setSubResult(operand2, operand1); } } @@ -646,11 +685,8 @@ return; } } - - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -679,10 +715,7 @@ } } - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -770,8 +803,7 @@ @Override public void execute() { int result = resolveOperand1() | resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -785,8 +817,7 @@ /** Moves a value into a register .*/ public void execute() { int result = resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -802,8 +833,7 @@ /** Clear bits in a register by a mask given by a second operand. */ public void execute() { int result = resolveOperand1() & (~resolveOperand2()); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -818,8 +848,7 @@ @Override public void execute() { int result = ~resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -951,6 +980,9 @@ if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to @@ -1040,8 +1072,16 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register - if (link) + if (link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + } + else { + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, BranchType.DIRECT_BRANCH); + } } public int getSuccessor(int pc) { @@ -1084,13 +1124,19 @@ + target.getType()); } + //if we're supposed to link, then write the previous address into the link register + if (link) { + regs.set(ARM_Registers.LR, previousAddress - 4); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); + } + else { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); + } + + //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); - - //if we're supposed to link, then write the previous address into the link register - if (link) - regs.set(ARM_Registers.LR, previousAddress - 4); } public int getSuccessor(int pc) { @@ -1376,6 +1422,11 @@ //finally, write the variable into a register regs.set(Rd, value); + + if (DBT_Options.profileDuringInterpretation) { + if (Rd == 15) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); + } } else { //we are store a value from a register to memory. Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1663,7 +1663,10 @@ arm2ir.getCurrentBlock().deleteNormalOut(); } - arm2ir.appendBranch(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); + if (link) + arm2ir.appendCall(pc + getOffset() + 8, lazy, pc + 4); + else + arm2ir.appendBranch(pc + getOffset() + 8, lazy, BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,7 +9,6 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.ByteAddressedMemory; -import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; @@ -39,11 +38,7 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - - if (DBT_Options.buildForSunVM) - memory = new DebugMemory(); - else - memory = new ByteAddressedMemory(); + memory = new ByteAddressedMemory(); } /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 17:43:21 UTC (rev 127) @@ -11702,10 +11702,13 @@ plantBranchToBlockDependentOnCondition(ppc2ir, instructionEndBlock, lazy, BI, !branch_if_cond_true, likely_to_fallthrough); } + + if (LK == 0) + ppc2ir.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + else + ppc2ir.appendCall(target_address, lazy, pc + 4); if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { - // Plant branch block - ppc2ir.appendBranch(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11731,7 +11734,6 @@ } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.appendBranch(target_address, lazy, BranchType.CALL); return -1; } } Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 17:43:21 UTC (rev 127) @@ -8,12 +8,29 @@ */ package org.binarytranslator.generic.branch; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; /** * Object capturing branches and jumps so that traces can avoid terminating on @@ -72,22 +89,12 @@ procedure = new ProcedureInformation(pc, ret, dest); procedures.put(dest, procedure); } + + registerBranch(pc, dest); } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param dest - * the destination of the branch instruction - */ - public void registerCall(int pc, int dest) { - registerCall(pc, dest, -1); - } /** - * Register a branch to the link register + * Register a function return. * * @param pc * the address of the branch instruction @@ -95,10 +102,14 @@ * the return address (value of the link register) */ public void registerReturn(int pc, int lr) { + ProcedureInformation procedure = getLikelyProcedure(pc); + if (procedure != null) { procedure.registerReturn(pc, lr); } + + registerBranch(pc, lr); } /** @@ -123,6 +134,7 @@ * Registers a branch from the address <code>origin</code> to the address <code>target</code>. * The type of branch is determined by <code>type</code>, which is an ordinal from the * {@link BranchType} enum. + * * @param origin * The address from which the branch occurs. * @param target @@ -130,24 +142,30 @@ * @param type * The most likely type of the branch. This is taken from the {@link BranchType} enum. */ - public void registerBranch(int origin, int target, int type) { - - if (DBT.VerifyAssertions) DBT._assert(type > 0 && type < BranchType.values().length); - - //Some branch types require a special registration (calls and returns) - switch (BranchType.values()[type]) { - case CALL: - registerCall(origin, target); - break; - - case RETURN: - registerReturn(origin, target); - break; - - default: - break; - } - + public void registerBranch(int origin, int target, BranchType type) { + + switch (type) { + case CALL: + throw new RuntimeException("Use the more specific registerCall() for these cases."); + + case RETURN: + registerReturn(origin, target); + break; + + default: + registerBranch(origin, target); + } + } + + /** + * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + private void registerBranch(int origin, int target) { //Perform the general branch registration, too Set<Integer> dests = branchSitesAndDestinations.get(origin); @@ -175,4 +193,126 @@ public Set<Integer> getKnownBranchTargets(int pc) { return branchSitesAndDestinations.get(pc); } + + public void loadFromXML(String filename) throws IOException { + + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(filename); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); + } catch (SAXException e) { + throw new IOException("File " + filename + " is not a valid XML file."); + } + + if (DBT.VerifyAssertions) DBT._assert(doc != null); + + Element root = doc.getDocumentElement(); + + if (!root.getNodeName().equals("branch-profile")) + throw new IOException("File is not a valid XML branch profile."); + + Node branches = null; + + for (int i = 0; i < root.getChildNodes().getLength(); i++) { + Node node = root.getChildNodes().item(0); + + if (node.getNodeName().equals("branches")) { + branches = node; + break; + } + } + + if (branches == null) + throw new IOException("File is not a valid XML branch profile."); + + for (int i = 0; i < branches.getChildNodes().getLength(); i++) { + Node siteNode = branches.getChildNodes().item(i); + + if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); + + for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { + Node target = siteNode.getChildNodes().item(n); + + if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + registerBranch(pc, targetAddress); + } + } + } + + /** + * Saves the branch profile of the current process space to the give file in XML format. + * + * @param filename + * The name of the file to which the branch profile is saved. + * @throws IOException + * Thrown if there is an error while creating the file. + */ + public void saveAsXML(String filename) throws IOException { + + FileOutputStream outputStream; + + try { + File f = new File(filename); + + if (!f.exists()) + f.createNewFile(); + + outputStream = new FileOutputStream(f); + } + catch (FileNotFoundException e) { + //this should not happen, as we just created the file + throw new IOException("Error creating file: " + filename); + } + + //Create an XML representation of the branch profile + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + try { + docBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IOException("Error creating parser to produce XML document."); + } + Document doc = docBuilder.newDocument(); + + Element root = doc.createElement("branch-profile"); + root.setAttribute("application", DBT_Options.executableFile); + doc.appendChild(root); + + Element branchesElement = doc.createElement("branches"); + root.appendChild(branchesElement); + + for (int pc : branchSitesAndDestinations.keySet()) { + Element branchSiteElement = doc.createElement("origin"); + branchesElement.appendChild(branchSiteElement); + branchSiteElement.setAttribute("address", Integer.toString(pc)); + + for (int target : getKnownBranchTargets(pc)) { + Element branchTargetElement = doc.createElement("target"); + branchSiteElement.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(target)); + } + } + + //Output the resulting XML document + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + + } catch (Exception e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -74,18 +74,22 @@ * </dd> * </dl> */ -public abstract class AbstractCodeTranslator implements OPT_Constants, OPT_Operators { +public abstract class AbstractCodeTranslator implements OPT_Constants, + OPT_Operators { /** The trace that we're currently translating code for. */ protected final DBT_Trace trace; - + /** VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace */ private static final VM_TypeReference psTref; /** Method ProcessSpace.doSysCall */ public static final VM_Method sysCallMethod; - /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ + /** + * VM_TypeReference of + * org.binarytranslator.generic.fault.BadInstructionException + */ public static final VM_Class badInstrKlass; /** Method BadInstructionException.<init> */ @@ -106,15 +110,17 @@ BadInstructionException.class).asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(badInstrKlass.getTypeRef(), + .findOrCreate( + badInstrKlass.getTypeRef(), VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); + VM_Atom + .findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference .findOrCreate(psTref, VM_Atom .findOrCreateAsciiAtom("recordUncaughtBranch"), VM_Atom - .findOrCreateAsciiAtom("(III)V")); + .findOrCreateAsciiAtom("(IIII)V")); recordUncaughtBranchMethod = recordUncaughtBranchMethRef .resolveInvokeSpecial(); } @@ -153,14 +159,18 @@ /** Map to locate HIR basic blocks to re-use translation within a trace */ protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - + private final static class UnresolvedJumpInstruction { public final OPT_Instruction instruction; + public final Laziness lazyStateAtJump; + public final int pc; + public final BranchType type; - - public UnresolvedJumpInstruction(OPT_Instruction instruction, Laziness lazyStateAtJump, int pc, BranchType type) { + + public UnresolvedJumpInstruction(OPT_Instruction instruction, + Laziness lazyStateAtJump, int pc, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; @@ -168,27 +178,30 @@ } } - /** - * List of unresolved direct branches. The destinations of direct branches are already known at - * translation time.*/ + /** + * List of unresolved direct branches. The destinations of direct branches are + * already known at translation time. + */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDirectBranches; - - /** - * List of unresolved dynamic branches. Dynamics branches have a destination address that is only - * determined at runtime. */ + + /** + * List of unresolved dynamic branches. Dynamics branches have a destination + * address that is only determined at runtime. + */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor * * @param context - * The JRVM generation context for this trace. + * The JRVM generation context for this trace. */ - protected AbstractCodeTranslator(OPT_GenerationContext context, DBT_Trace trace) { - - //Store the trace that we're invoked from + protected AbstractCodeTranslator(OPT_GenerationContext context, + DBT_Trace trace) { + + // Store the trace that we're invoked from this.trace = trace; - + // Make copies of popular variables gc = context; ps = ((DBT_Trace) (gc.method)).ps; @@ -211,7 +224,7 @@ unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); } - + /** Returns the number of previously translated instructions within this trace. */ public int getNumInstructions() { return numberOfInstructions; @@ -230,10 +243,10 @@ if (!DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } - - //Resolve all open direct first + + // Resolve all open direct first resolveAllDirectBranches(); - + if (DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } @@ -263,15 +276,14 @@ // Create next block nextBlock = createBlockAfterCurrent(); // Finish block to return and exit - appendTraceExit(lazy, - new OPT_IntConstantOperand(pc)); + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); // Move currentBlock along currentBlock = nextBlock; } else { do { if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - + // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); @@ -285,7 +297,7 @@ // Move currentBlock along currentBlock = nextBlock; currentPC = pc; - + if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); @@ -370,22 +382,23 @@ gc.cfg.linkInCodeOrder(currentBlock, newBlock); gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - /*if (DBT.VerifyAssertions) - DBT._assert(currentBlock.isOut(nxtBlock));*/ + /* + * if (DBT.VerifyAssertions) DBT._assert(currentBlock.isOut(nxtBlock)); + */ if (currentBlock.isOut(nxtBlock)) { currentBlock.deleteOut(nxtBlock); currentBlock.insertOut(newBlock); newBlock.insertOut(nxtBlock); - } - else { + } else { currentBlock.insertOut(newBlock); } if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + currentBlock)); } - + return newBlock; } @@ -404,7 +417,8 @@ gc.cfg.linkInCodeOrder(newBlock, nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created non-cfg block (%s) after current (%s).", + newBlock, currentBlock)); } return newBlock; } @@ -414,7 +428,7 @@ * into the CFG and code ordering * * @param afterBlock - * The block after which the new block is to be created. + * The block after which the new block is to be created. * @return the new basic block */ public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { @@ -432,9 +446,10 @@ newBlock.insertOut(nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, afterBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + afterBlock)); } - + return newBlock; } @@ -442,7 +457,7 @@ * Append a HIR instruction to the current basic block * * @param i - * The instruciton that is to be appended to the current bloc. + * The instruciton that is to be appended to the current bloc. */ public void appendInstruction(OPT_Instruction i) { if (i.bcIndex == UNKNOWN_BCI) { @@ -461,7 +476,7 @@ * Generate a branch profile operand for the current instruction * * @param likely - * Does this branch have a likely hint? + * Does this branch have a likely hint? */ public OPT_BranchProfileOperand getConditionalBranchProfileOperand( boolean likely) { @@ -491,11 +506,11 @@ * Register a mapping between a pc and lazy and a hir block * * @param pc - * The program counter whose translation the basic bock represents. + * The program counter whose translation the basic bock represents. * @param lazy - * The lazy state that is assumed for this basic block. + * The lazy state that is assumed for this basic block. * @param hirBlock - * The block that is to be registered. + * The block that is to be registered. */ protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { blockMap.put(lazy.makeKey(pc), hirBlock); @@ -505,175 +520,267 @@ * Find if there's already a translation for a given pc and laziness * * @param pc - * The program counter address at which the returned basic block shall start. + * The program counter address at which the returned basic block + * shall start. * @param lazy - * The lazy state assumed within the returned trace. - * @return - * An appropriate basic block or null if no translation exists. + * The lazy state assumed within the returned trace. + * @return An appropriate basic block or null if no translation exists. */ protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { return blockMap.get(lazy.makeKey(pc)); } /** - * Create a HIR Goto instruction that jumps to the address <code>targetPc</code>. There's - * a caveat on using this that there are no other out edges for this BB. + * Create a HIR Goto instruction that jumps to the address + * <code>targetPc</code>. There's a caveat on using this that there are no + * other out edges for this BB. * * @param targetPC - * The address where we shall jump to. + * The address where we shall jump to. * @param targetLaziness - * The current at the point of jump. + * The current at the point of jump. * @param branchType - * The type of branch that best describes this jump. + * The type of branch that best describes this jump. */ public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { - //Place a GOTO instruction at this point. However, this instruction - //serves more as a placeholder and might be mutated later on. + if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); + + appendStaticBranch(targetPC, targetLaziness, branchType, -1); + } + + /** + * Create a HIR Goto instruction that jumps to the address + * <code>targetPc</code>. There's a caveat on using this that there are no + * other out edges for this BB. + * + * @param targetPC + * The address where we shall jump to. + * @param targetLaziness + * The current at the point of jump. + * @param branchType + * The type of branch that best describes this jump. + */ + public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { + + appendStaticBranch(targetPC, targetLaziness, BranchType.CALL, retAddr); + } + + private void appendStaticBranch(int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { + // Place a GOTO instruction at this point. However, this instruction + // serves more as a placeholder and might be mutated later on. OPT_Instruction jump = Goto.create(GOTO, null); appendInstruction(jump); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC, branchType); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( + jump, (Laziness) targetLaziness.clone(), targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); - //Notify the branch profile about certain types of branches - switch (branchType) { - case CALL: - ps.branchInfo.registerCall(currentPC, targetPC); - return; - - case RETURN: + if (branchType == BranchType.CALL) + ps.branchInfo.registerCall(currentPC, targetPC, retAddr); + else + if (branchType == BranchType.RETURN) ps.branchInfo.registerReturn(currentPC, targetPC); - return; + else + ps.branchInfo.registerBranch(currentPC, targetPC, branchType); + } + + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param retAddr + * The address, to which the function call will (most likely) return. + */ + public void appendCall(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, int retAddr) { + + appendDynamicBranch(targetAddress, lazyStateAtJump, BranchType.CALL, retAddr); + } + + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param branchType + * The type of jump. + */ + public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { + + if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); + + appendDynamicBranch(targetAddress, lazyStateAtJump, branchType, -1); + } - default: - return; - } + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param branchType + * The type of jump. + * @param retAddr + * The address, to which the function call will (most likely) return or an arbitrary value, if + * branchType is not BranchType.CALL. + */ + private void appendDynamicBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType, int retAddr) { + + OPT_BasicBlock fallThrough = createBlockAfterCurrent(); + OPT_Instruction switchInstr; + switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); + appendInstruction(switchInstr); + + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + unresolvedDynamicBranches.add(unresolvedInfo); + + setCurrentBlock(fallThrough); + appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + } - /** Resolve all unresolved direct branch instructions. */ + /** Resolve all unresolved direct branch instructions. */ private void resolveAllDirectBranches() { - + for (int i = 0; i < unresolvedDirectBranches.size(); i++) { - - //Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(unresolvedDirectBranches.size() - 1); + + // Get the jump that we're supposed to resolve + UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches + .remove(unresolvedDirectBranches.size() - 1); int targetPc = unresolvedInstr.pc; Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; OPT_Instruction gotoInstr = unresolvedInstr.instruction; - - if (DBT.VerifyAssertions) DBT._assert(Goto.conforms(gotoInstr)); - - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, unresolvedInstr.type); - + + if (DBT.VerifyAssertions) + DBT._assert(Goto.conforms(gotoInstr)); + + OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, + unresolvedInstr.type); + if (DBT_Options.debugBranchResolution) { - report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); + report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + + targetBB); } - + // Fix up instruction Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); gotoInstr.getBasicBlock().insertOut(targetBB); - + if (DBT_Options.debugBranchResolution) { - report("Properly resolving goto in block " - + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " - + targetBB); + report("Properly resolving goto in block " + gotoInstr.getBasicBlock() + + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } } } /** - * Resolves a branch target to an actual basic block. In case the jump target is not yet part - * of this trace, this method also takes a decision about whether the target shall be translated - * into the trace. + * Resolves a branch target to an actual basic block. In case the jump target + * is not yet part of this trace, this method also takes a decision about + * whether the target shall be translated into the trace. * - * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, - * this method will always end the current trace, just returning the address of the next instruction. + * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, + * this method will always end the current trace, just returning the address + * of the next instruction. * * @param targetPc - * The address of the target basic block that. + * The address of the target basic block that. * @param lazyStateAtJump - * The lazy state with which we would be entering the block. - * @return - * A basic block that is equivalent to the program counter address <code>targetPc</code> in the - * original binary. + * The lazy state with which we would be entering the block. + * @return A basic block that is equivalent to the program counter address + * <code>targetPc</code> in the original binary. */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, Laziness lazyStateAtJump, BranchType branchtype) { - //Resolve the address of the target block + private OPT_BasicBlock resolveBranchTarget(int targetPc, + Laziness lazyStateAtJump, BranchType branchtype) { + // Resolve the address of the target block OPT_BasicBlock targetBB = findMapping(targetPc, lazyStateAtJump); - - //If the target is already part of this trace, then just use the precompiled target + + // If the target is already part of this trace, then just use the + // precompiled target if (targetBB != null) return targetBB; - - /* The target Block is not yet translated. - * We do not want to translate it into the current trace if - * a) DBT_Options.singleInstrTranslation is enabled - * b) The jump target has already been compiled as a separate method within the code cache - * c) The trace is already too long - * d) the branch is supposedly a CALL or RETURN + + /* + * The target Block is not yet translated. We do not want to translate it + * into the current trace if a) DBT_Options.singleInstrTranslation is + * enabled b) The jump target has already been compiled as a separate method + * within the code cache c) The trace is already too long d) the branch is + * supposedly a CALL or RETURN */ - if (DBT_Options.singleInstrTranslation == true || - ps.codeCache.tryGet(targetPc) != null || - shallTraceStop() || - branchtype == BranchType.CALL || - branchtype == BranchType.RETURN) { - - //Just exit the trace and continue at the target address in a new trace + if (DBT_Options.singleInstrTranslation == true + || ps.codeCache.tryGet(targetPc) != null || shallTraceStop() + || branchtype == BranchType.CALL || branchtype == BranchType.RETURN) { + + // Just exit the trace and continue at the target address in a new trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); - - if (DBT_Options.debugBranchResolution) System.out.println("Resolving branch to next block."); + + if (DBT_Options.debugBranchResolution) + System.out.println("Resolving branch to next block."); } targetBB = currentBlock; appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); registerMapping(targetPc, lazyStateAtJump, targetBB); - } - else { - //Otherwise we will translate the jump into the trace + } else { + // Otherwise we will translate the jump into the trace translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); targetBB = findMapping(targetPc, lazyStateAtJump); } - - if (DBT.VerifyAssertions) DBT._assert(targetBB != null); - + + if (DBT.VerifyAssertions) + DBT._assert(targetBB != null); + return targetBB; } /** - * Resolves all dynamic branches that have been added with + * Resolves all dynamic branches that have been added with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ private void resolveDynamicBranches() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); + + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches + .get(i); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - + resolveSingleDynamicJump(unresolvedSwitch, branchDests); } } - /** - * Resolves a single dynamic jump that has previously been created with + /** + * Resolves a single dynamic jump that has previously been created with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. * * @param lazy - * The lazy state of the jump that is to be resolved. + * The lazy state of the jump that is to be resolved. * @param lookupswitch - * Each dynamic jump is converted to a switch statement. This is the switch statement for the current jump. + * Each dynamic jump is converted to a switch statement. This is the + * switch statement for the current jump. * @param destinations - * A list of known destinations that this dynamic jumps branches to. + * A list of known destinations that this dynamic jumps branches to. */ - private void resolveSingleDynamicJump(UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) throws Error { - - if (DBT.VerifyAssertions) DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); - + private void resolveSingleDynamicJump( + UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) + throws Error { + + if (DBT.VerifyAssertions) + DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); + OPT_Instruction lookupswitch = unresolvedJump.instruction; OPT_BranchOperand default_target = LookupSwitch.getDefault(lookupswitch); OPT_Operand value = LookupSwitch.getValue(lookupswitch); - + if (destinations != null) { if ((destinations.size() > 1) || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target @@ -685,24 +792,28 @@ .size() * 3); int match_no = 0; for (int dest_pc : destinations) { - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); - LookupSwitch.setMatch(lookupswitch, match_no, new OPT_IntConstantOperand(dest_pc)); - LookupSwitch.setTarget(lookupswitch, match_no, target .makeJumpTarget()); - LookupSwitch.setBranchProfile(lookupswitch, match_no, new OPT_BranchProfileOperand(branchProb)); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, + unresolvedJump.lazyStateAtJump, unresolvedJump.type); + + LookupSwitch.setMatch(lookupswitch, match_no, + new OPT_IntConstantOperand(dest_pc)); + LookupSwitch.setTarget(lookupswitch, match_no, target + .makeJumpTarget()); + LookupSwitch.setBranchProfile(lookupswitch, match_no, + new OPT_BranchProfileOperand(branchProb)); lookupswitch.getBasicBlock().insertOut(target); match_no++; } } else { int dest_pc = destinations.iterator().next(); - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, + unresolvedJump.lazyStateAtJump, unresolvedJump.type); + IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, - new OPT_IntConstantOperand(dest_pc), - OPT_ConditionOperand.EQUAL(), target.makeJumpTarget(), - OPT_BranchProfileOperand.likely()); + new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), + target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); lookupswitch.getBasicBlock().insertOut(target); } } else { @@ -710,44 +821,20 @@ lookupswitch.remove(); } } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - */ - public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { - - OPT_BasicBlock fallThrough = createBlockAfterCurrent(); - OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); - appendInstruction(switchInstr); - - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); - } - /** - * Resolves all dynamic jump targets by making sure the respective basic blocks exist. + * Resolves all dynamic jump targets by making sure the respective basic + * blocks exist. */ private void resolveAllDynamicBranchTargets() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); - + + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches + .get(i); + Laziness lazy = unresolvedSwitch.lazyStateAtJump; Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - + if (branchDests != null) { for (int dest_pc : branchDests) { resolveBranchTarget(dest_pc, lazy, unresolvedSwitch.type); @@ -765,31 +852,29 @@ * instruction to translate) */ public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - //nextBlock = createBlockAfterCurrentNotInCFG(); - + // Copy the value into the register specified by gc.resultReg. - appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(gc.resultReg, VM_TypeReference.Int), nextPc)); + appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand( + gc.resultReg, VM_TypeReference.Int), nextPc)); resolveLaziness(laziness); appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); currentBlock.insertOut(finishBlock); if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - - //currentBlock = nextBlock; } /** - * Should the trace be stopped as soon as possible? This function can be used to steer how large a single - * trace may be. Return true if the target size for the trace is about to be or has been exceeded. + * Should the trace be stopped as soon as possible? This function can be used + * to steer how large a single trace may be. Return true if the target size + * for the trace is about to be or has been exceeded. * * @return true => try to stop the trace */ protected boolean shallTraceStop() { if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { return true; - } else { + } else { switch (gc.options.getOptLevel()) { case 0: return numberOfInstructions > DBT_Options.instrOpt0; @@ -805,23 +890,23 @@ * Register a branch and link instruction * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param ret - * the address returned to + * the address returned to * @param dest - * the destination of the branch instruction + * the destination of the branch instruction */ public void registerBranchAndLink(int pc, int ret, int dest) { ps.branchInfo.registerCall(pc, ret, dest); } /** - * Returns a vector of likely branch targets for the branch at address <code>pc</code>. + * Returns a vector of likely branch targets for the branch at address + * <code>pc</code>. * * @param pc - * The location at which the branch occurs. - * @return - * A set of likely destinations for that jump. + * The location at which the branch occurs. + * @return A set of likely destinations for that jump. */ private Set<Integer> getLikelyJumpTargets(int pc) { return ps.branchInfo.getKnownBranchTargets(pc); @@ -832,7 +917,7 @@ * the trace? * * @param pc - * the address of the branch and link instruction + * the address of the branch and link instruction * @return whether the trace should continue */ public boolean traceContinuesAfterBranchAndLink(int pc) { @@ -886,13 +971,14 @@ * Appends a system call to the current basic block. * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * address of system call instruction + * address of system call instruction */ public void appendSystemCall(Laziness lazy, int pc) { - //We need to make sure that all registers contain their latest values, before - //performing the actual system call. + // We need to make sure that all registers contain their latest values, + // before + // performing the actual system call. resolveLaziness(lazy); spillAllRegisters(); @@ -904,7 +990,7 @@ OPT_Operand psRef = gc.makeLocal(1, psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall + // doSysCall Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, @@ -921,13 +1007,14 @@ * Plant a throw of a bad instruction exception * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * the program counter of the bad instruction + * the program counter of the bad instruction */ public void appendThrowBadInstruction(Laziness lazy, int pc) { - //We need to make sure that all registers contain their latest values, before - //throwing the bad instruction exception. + // We need to make sure that all registers contain their latest values, + // before + // throwing the bad instruction exception. resolveLaziness(lazy); spillAllRegisters(); @@ -946,7 +1033,7 @@ n.position = gc.inlineSequence; n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; appendInstruction(n); - + OPT_Operand psRef = gc.makeLocal(1, psTref); OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( @@ -971,8 +1058,7 @@ appendInstruction(t); - appendTraceExit(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); + appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); } /** @@ -980,28 +1066,31 @@ * for call * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param destination - * the register operand holding the destination - * @param code - * a code that can be a hint of the branch type + * the register operand holding the destination + * @param branchType + * The type of the uncaught branch + * @param retAddr + * An optional return address, in case the branch is a call. Otherwise, this value is ignored. */ - private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType) { + private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType, int retAddr) { // Is it sensible to record this information? if ((gc.options.getOptLevel() > 0) && (DBT_Options.plantUncaughtBranchWatcher)) { // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 4); + OPT_Instruction s = Call.create(CALL, null, null, null, null, 5); OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( recordUncaughtBranchMethod.getMemberRef().asMethodReference(), recordUncaughtBranchMethod); OPT_Operand psRef = gc.makeLocal(1, psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch - // instruction + // instruction Call.setParam(s, 2, destination); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch code - // value + Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type + Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address + // value Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, new OPT_AddressConstantOperand( @@ -1135,7 +1224,8 @@ * Get/create a temporary validation variable * * @param num - * a hint to allow for reuse of temps across instructions */ + * a hint to allow for reuse of temps across instructions + */ public OPT_RegisterOperand getTempValidation(int num) { if (DBT.VerifyAssertions) DBT._assert(num == 0); @@ -1149,100 +1239,108 @@ return new OPT_RegisterOperand(result, VM_TypeReference.VALIDATION_TYPE); } } - + /** - * Inserts code into the current block that will use the process space's interpreter - * to execute the given instructions. - * + * Inserts ... [truncated message content] |
From: <mic...@us...> - 2007-06-14 17:19:15
|
Revision: 132 http://svn.sourceforge.net/pearcolator/?rev=132&view=rev Author: michael_baer Date: 2007-06-14 10:19:16 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Moving further towards Thumb support Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) @@ -70,7 +70,7 @@ /** * Set this to true to translate only one instruction at a time. */ - public static boolean singleInstrTranslation = true; + public static boolean singleInstrTranslation = false; /** * Eliminate unneeded filling of register @@ -126,10 +126,12 @@ public final static int GID = 100; /** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */ - private final static HashMap<String, String> dbtArguments = new HashMap<String, String>(); + private static HashMap<String, String> dbtArguments = null; /** Read and parse the command line arguments. */ public static void parseArguments(String[] args) { + + dbtArguments = new HashMap<String, String>(); try { ArrayList<String> remainingArguments = new ArrayList<String>(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) @@ -17,6 +17,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -40,11 +41,19 @@ * @return A disassembled ARM instruction. */ public final static DisassembledInstruction disassemble(int address, - ProcessSpace ps) { + ARM_ProcessSpace ps) { - int binaryInstruction = ps.memory.loadInstruction32(address); - Instruction decodedInstruction = ARM_InstructionDecoder.decode(binaryInstruction); + Instruction decodedInstruction; + if ((address & 0x1) == 1) { + short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE); + decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(address); + decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); + } + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); decodedInstruction.visit(disassembler); @@ -170,7 +179,7 @@ return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), op.getShiftAmount()); - case PcRelative: + case RegisterOffset: if (address != -1) return String.format("#0x%x", op.getOffset() + address + 8); else Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-14 17:19:16 UTC (rev 132) @@ -3,312 +3,527 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** - * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class - * that represents the given instruction. + * This class decodes an ARM or Thumb instruction and uses a user-supplied + * ARM_InstructionFactory to create a class that represents the given + * instruction. * - * The decoder first performs a pseudo-switch on bits 27-25 of the instruction. - * For performance reasons, the switch is implemented as an array lookup (using the {@link #prefixDecoders} array), - * with single {@link Decoder} classes implementing the cases. - * - * ARM has a very cluttered opcode map, which is why the decoding process does not look very tidy. - * However, the presented decoded scheme has been derived by producing all possible instructions and then - * letting a data mining tool (specifically: Weka) create a decision tree to decode the single - * instruction classes. This has two implications: - * <ol> - * <li>The decoder is correct (at least, when I didn't introduce any typos), as Weka verified an error rate of 0% for this decision tree.</li> - * <li>The decoder is reasonably fast, considering Weka tries to build a shallow decision tree.</li> + * ARM has a very cluttered opcode map, which is why the decoding process does + * not look very tidy. However, the presented decoded scheme has been derived by + * producing all possible instructions and then letting a data mining tool + * (specifically: Weka) create a decision tree to decode the single instruction + * classes. This has two implications: + * <ol> + * <li>The decoder is correct (at least, if I didn't introduce any typos), as + * Weka verified an error rate of 0% for this decision tree.</li> + * <li>The decoder is reasonably fast, considering Weka tries to build a + * shallow decision tree.</li> * </ol> * * @author Michael Baer - * + * */ public class ARM_InstructionDecoder { - /** - * This table is used to perform a lookup on bits 25-27 of an instruction. - * According to the result of this lookup, the {@link Decoder} instances within this - * array perform the subsequent instruction decoding. */ - private static Decoder[] prefixDecoders = { - new decoder_000(), new decoder_001(), - new decoder_010(), new decoder_011(), - new decoder_100(), new decoder_101(), - new decoder_110(), new decoder_111() - }; - - /** - * This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. - * It is being lazily initialized once it is used for the first time. */ + /** + * This static field caches the default {@link ARM_InstructionFactory} + * implementation, which is used by {@link #decode(int)}. It is being + * lazily initialized once it is used for the first time. + */ private static DefaultFactory _defaultFactory; - - /** - * This class performs additional instruction decoding, after bits 25-27 of an instruction have been - * determined. The class is basically just a way of substituting a switch by an array lookup+virtual method call. - * */ - private static abstract class Decoder { - abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); - } - - /** Decoder which assumes that bits 27-25 == 000. */ - private static class decoder_000 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** + * + * The decoder first performs a pseudo-switch on bits 27-25 of the + * instruction. For performance reasons, the switch is implemented as an array + * lookup (using the {@link #prefixDecoders} array), with single + * {@link Decoder} classes implementing the cases. + * + */ + public static class ARM32 { + /** + * This table is used to perform a lookup on bits 25-27 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { new decoder_000(), + new decoder_001(), new decoder_010(), new decoder_011(), + new decoder_100(), new decoder_101(), new decoder_110(), + new decoder_111() }; + /** + * This class performs additional instruction decoding, after bits 25-27 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); + } + + /** Decoder which assumes that bits 27-25 == 000. */ + private static class decoder_000 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + byte bits_7_4 = (byte) Utils.getBits(instr, 4, 7); + + if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 20) == false + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createMoveFromStatusRegister(instr); + } + + if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { + // bits 7-4 == 1 || bits 7-4 == 3 + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == + // true && Utils.getBit(instr, 20) == false + return factory.createBranchExchange(instr); + } + + if ((bits_7_4 & 9) == 9) { + // bits7-4 = 1xx1 + if (bits_7_4 == 9) { + if (Utils.getBit(instr, 23)) { + return factory.createLongMultiply(instr); + } else { + if (Utils.getBit(instr, 24)) + return factory.createSwap(instr); + else + return factory.createIntMultiply(instr); + } + } else + return factory.createSingleDataTransfer(instr); + } + + return factory.createDataProcessing(instr); } - - byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); + } - if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else - return factory.createMoveFromStatusRegister(instr); + /** Decoder which assumes that bits 27-25 == 001. */ + private static class decoder_001 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + if (((instr & 0x01900000) == 0x01000000)) { + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 20) == false + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createDataProcessing(instr); } - - if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { - //bits 7-4 == 1 || bits 7-4 == 3 - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false - return factory.createBranchExchange(instr); + } + + /** Decoder which assumes that bits 27-25 == 010. */ + private static class decoder_010 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); + } } - - if ((bits_7_4 & 9) == 9) { - //bits7-4 = 1xx1 - if (bits_7_4 == 9) { - if (Utils.getBit(instr, 23)) { - return factory.createLongMultiply(instr); - } - else { - if (Utils.getBit(instr, 24)) - return factory.createSwap(instr); - else - return factory.createIntMultiply(instr); - } + } + + /** Decoder which assumes that bits 27-25 == 011. */ + private static class decoder_011 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? or bit4==true + if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); } - else - return factory.createSingleDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 001. */ - private static class decoder_001 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); - } - - if (((instr & 0x01900000) == 0x01000000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else + /** Decoder which assumes that bits 27-25 == 100. */ + private static class decoder_100 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); + } + + return factory.createBlockDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 010. */ - private static class decoder_010 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 101. */ + private static class decoder_101 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createBranchExchange(instr); + } + + return factory.createBranch(instr); } - else { - return factory.createSingleDataTransfer(instr); + } + + /** Decoder which assumes that bits 27-25 == 110. */ + private static class decoder_110 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + return factory.createCoprocessorDataTransfer(instr); } } - } - - /** Decoder which assumes that bits 27-25 == 011. */ - private static class decoder_011 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? or bit4==true - if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 111. */ + private static class decoder_111 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 24)) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSoftwareInterrupt(instr); + } + } else { + if (Utils.getBit(instr, 4)) { + return factory.createCoprocessorRegisterTransfer(instr); + } else { + return factory.createCoprocessorDataProcessing(instr); + } + } } - else { - return factory.createSingleDataTransfer(instr); + } + + /** + * Decodes a given ARM instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(int instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } + + public static int fastpathCount = 0; + + /** + * Decodes a binary ARM instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + + if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { + + // Check condition!=never? + if ((instruction & 0xF0000000) != 0xF0000000) { + + if ((instruction & 0x0F000000) == 0x02000000) { + fastpathCount++; + return factory.createDataProcessing(instruction); + } + } + + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } else { + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); } } } - /** Decoder which assumes that bits 27-25 == 100. */ - private static class decoder_100 extends Decoder { + /** + * The instruction decoder for Thumb instructions. It works similar to the ARM32 decoder and has + * also been created using the Weka datamining tool. + */ + public static class Thumb { + /** + * This class performs additional instruction decoding, after bits 12-15 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(short instr, ARM_InstructionFactory<T> factory); + } + + /** This table is used to perform a lookup on bits 12-15 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new Decoder_0100(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new DataProcessing_Decoder(), new Decoder_1011(), + new BlockDataTransfer_Decoder(), new Decoder_1101(), + new Decoder_1110(), new Decoder_1111()}; + + private static class DataProcessing_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createDataProcessing(instr); } - - return factory.createBlockDataTransfer(instr); } - } - - /** Decoder which assumes that bits 27-25 == 101. */ - private static class decoder_101 extends Decoder { + + private static class SingleDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createBranchExchange(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createSingleDataTransfer(instr); } - - return factory.createBranch(instr); } - } - - /** Decoder which assumes that bits 27-25 == 110. */ - private static class decoder_110 extends Decoder { + + private static class BlockDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - return factory.createCoprocessorDataTransfer(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createBlockDataTransfer(instr); + } } - } - - /** Decoder which assumes that bits 27-25 == 111. */ - private static class decoder_111 extends Decoder { + + private static class Decoder_0100 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 24)) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); } else { - return factory.createSoftwareInterrupt(instr); + //bit8==bit9==bit10==1? + if ((instr & 0x70) == 0x70) + return factory.createBranchExchange(instr); + + return factory.createDataProcessing(instr); } } - else { - if (Utils.getBit(instr, 4)) { - return factory.createCoprocessorRegisterTransfer(instr); + } + + private static class Decoder_1011 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 10)) { + return factory.createBlockDataTransfer(instr); } else { - return factory.createCoprocessorDataProcessing(instr); + return factory.createDataProcessing(instr); } } } - } - - /** - * Decodes a given ARM instruction and returns an object representation of it. - * @param instruction - * A binary ARM instruction, that is to be decoded. - * @return - * A version of the instruction, which has been decoded into an instance of {@link Instruction}. - * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the - * returned instance. - */ - public static Instruction decode(int instruction) { - if (_defaultFactory == null) - _defaultFactory = new DefaultFactory(); - return decode(instruction, _defaultFactory); - } + private static class Decoder_1101 extends Decoder { - public static int fastpathCount = 0; - - /** - * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} - * to create an object representation of the decoded instruction. - * @param <T> - * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. - * @param instruction - * A binary representation of the instruction that is to be decoded. - * @param factory - * A factory, that will create object instances of the instruction. - * @return - * An object representation of the decoded instruction. - */ - static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); + } + else { + //bit9==bit10==bit11==1? + if ((instr & 0xE0) == 0xE0) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createBranch(instr); + } + } + } - if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { - - //Check condition!=never? - if ((instruction & 0xF0000000) != 0xF0000000) { + private static class Decoder_1110 extends Decoder { - if ((instruction & 0x0F000000) == 0x02000000) { - fastpathCount++; - return factory.createDataProcessing(instruction); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + if (Utils.getBit(instr, 0)) + return factory.createUndefinedInstruction(instr); + else + return factory.createBranchExchange(instr); } + else { + return factory.createBranch(instr); + } } + } - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + private static class Decoder_1111 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createBranch(instr); + } + else { + return factory.createDataProcessing(instr); + } + } } - else { - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + + /** + * Decodes a binary Thumb instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { + + int bits_12_15 = Utils.getBits(instruction, 12, 15); + return prefixDecoders[bits_12_15].decode(instruction, factory); } + + /** + * Decodes a given Thumb instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(short instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } } - + /** - * An interface to a factory class, which will create the actual object representations of the - * instruction classes decoded by {@link ARM_InstructionDecoder}. - * + * An interface to a factory class, which will create the actual object + * representations of the instruction classes decoded by + * {@link ARM_InstructionDecoder}. + * * @param <T> - * The type of the object representations, that shall be created when an ARM instruction is decoded. + * The type of the object representations, that shall be created when + * an ARM instruction is decoded. */ interface ARM_InstructionFactory<T> { T createDataProcessing(int instr); + T createSwap(int instr); + T createSingleDataTransfer(int instr); + T createBlockDataTransfer(int instr); + T createIntMultiply(int instr); + T createLongMultiply(int instr); + T createSoftwareInterrupt(int instr); + T createBranch(int instr); + T createBranchExchange(int instr); + T createCoprocessorDataTransfer(int instr); + T createCoprocessorDataProcessing(int instr); + T createCoprocessorRegisterTransfer(int instr); + T createMoveFromStatusRegister(int instr); + T createMoveToStatusRegister(int instr); + T createUndefinedInstruction(int instr); - + T createDataProcessing(short instr); + T createSwap(short instr); + T createSingleDataTransfer(short instr); + T createBlockDataTransfer(short instr); - T createshortMultiply(short instr); + + T createIntMultiply(short instr); + T createLongMultiply(short instr); - T createSoftwareshorterrupt(short instr); + + T createSoftwareInterrupt(short instr); + T createBranch(short instr); + T createBranchExchange(short instr); + T createCoprocessorDataTransfer(short instr); + T createCoprocessorDataProcessing(short instr); + T createCoprocessorRegisterTransfer(short instr); + T createMoveFromStatusRegister(short instr); + T createMoveToStatusRegister(short instr); + T createUndefinedInstruction(short instr); } - + /** - * A default implementation of the ARM instruction factory, which will create the - * appropriate classes from the {@link ARM_Instructions} namespace. + * A default implementation of the ARM instruction factory, which will create + * the appropriate classes from the {@link ARM_Instructions} namespace. */ - private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { + private static class DefaultFactory implements + ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { return new BlockDataTransfer(instr); @@ -371,79 +586,63 @@ } public Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(instr); } public Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(instr); } public Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(instr); } public Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorRegisterTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + return new DataProcessing(instr); } public Instruction createLongMultiply(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support long multiplications."); } public Instruction createMoveFromStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createMoveToStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createSingleDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new SingleDataTransfer(instr); } - public Instruction createSoftwareshorterrupt(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createSoftwareInterrupt(short instr) { + return new SoftwareInterrupt(instr); } public Instruction createSwap(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support SWAP instructions."); } public Instruction createUndefinedInstruction(short instr) { - // TODO Auto-generated method stub return null; } - public Instruction createshortMultiply(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createIntMultiply(short instr) { + return new IntMultiply(instr); } - } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) @@ -2,6 +2,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -149,7 +150,7 @@ /** Describes the type of the operand. */ public enum Type { Immediate, - PcRelative, + RegisterOffset, Register, ImmediateShiftedRegister, RegisterShiftedRegister, @@ -175,8 +176,8 @@ } /** Creates an operand wrapper representing an offset to the pc.*/ - public static OperandWrapper createPcRelative(int offset) { - return new PcRelativeOperand(offset); + public static OperandWrapper createRegisterOffset(byte register, int offset) { + return new RegisterOffsetOperand(register, offset); } public static OperandWrapper createRegisterShiftImmediate(byte register, ShiftType type, byte amount) { @@ -329,17 +330,19 @@ } } - protected static class PcRelativeOperand extends OperandWrapper { + protected static class RegisterOffsetOperand extends OperandWrapper { protected final int offset; + protected final byte register; - protected PcRelativeOperand(int offset) { + protected RegisterOffsetOperand(byte register, int offset) { this.offset = offset; + this.register = register; } @Override public byte getRegister() { - return 15; + return register; } @Override @@ -349,7 +352,7 @@ @Override public Type getType() { - return Type.PcRelative; + return Type.RegisterOffset; } } @@ -463,6 +466,46 @@ protected final OperandWrapper operand2; public DataProcessing(short instr) { + + if (Utils.getBits(instr, 12, 15) == 0xA) { + //add to SP or PC (load address) + opcode = Opcode.ADD; + updateConditionCodes = false; + Rd = (byte)Utils.getBits(instr, 8, 10); + Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + + return; + } + + if (Utils.getBits(instr, 12, 15) == 0xB) { + //add offset to SP + updateConditionCodes = false; + opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; + Rd = (byte)ARM_Registers.SP; + Rn = (byte)ARM_Registers.SP; + operand2 = OperandWrapper.createImmediate(instr & 0x7F); + + return; + } + + if (Utils.getBits(instr, 14, 15) == 0x7) { + //first instruction of a long bl/blx + if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); + + //extract and sign-extend the offset + int offset = Utils.getBits(instr, 0, 10); + offset = Utils.signExtend(offset, 11) << 12; + operand2 = OperandWrapper.createImmediate(offset); + + opcode = Opcode.MOV; + Rd = ARM_Registers.LR; + updateConditionCodes = false; + Rn = 0; + + return; + } + if (Utils.getBits(instr, 13, 15) == 0) { //shift by immediate, add/subtract register or add/subtract immediate Rd = (byte)Utils.getBits(instr, 0, 2); @@ -506,99 +549,130 @@ opcode = Opcode.SUB; break; default: - throw new RuntimeException("Values other than 0-4 cannot be represented within 2 bits."); + throw new RuntimeException("Values other than 0-3 cannot be represented within 2 bits."); } } else { - Rd = (byte)Utils.getBits(instr, 0, 2); - byte finalRn = (byte)Utils.getBits(instr, 3, 5); - updateConditionCodes = true; - switch (Utils.getBits(instr, 6, 9)) { - case 0: - opcode = Opcode.AND; - operand2 = OperandWrapper.createRegister(Rd); - break; - case 1: - opcode = Opcode.EOR; - operand2 = OperandWrapper.createRegister(Rd); - break; + if (Utils.getBit(instr, 10)) { + //special data processing + Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); + Rn = Rd; + operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); + updateConditionCodes = true; - case 2: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); - break; + switch (Utils.getBits(instr, 8, 9)) { + case 0: + opcode = Opcode.ADD; + break; + + case 1: + opcode = Opcode.CMP; + break; + + case 2: + opcode = Opcode.MOV; + break; + + case 3: + throw new RuntimeException("This case is actually a BranchExchange."); + + default: + throw new RuntimeException("Only the values 0-3 can be represented within 2 bits."); + } + } + else { + //data processing-register + Rd = (byte)Utils.getBits(instr, 0, 2); + byte finalRn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; - case 3: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); - break; + switch (Utils.getBits(instr, 6, 9)) { + case 0: + opcode = Opcode.AND; + operand2 = OperandWrapper.createRegister(Rd); + break; + case 1: + opcode = Opcode.EOR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 2: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); + break; + + case 3: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); + break; + + case 4: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); + break; + + case 5: + opcode = Opcode.ADC; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 6: + opcode = Opcode.SBC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 7: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); + break; + + case 8: + opcode = Opcode.TST; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 9: + opcode = Opcode.RSB; + operand2 = OperandWrapper.createImmediate(0); + break; + + case 10: + opcode = Opcode.CMP; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 11: + opcode = Opcode.CMN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 12: + opcode = Opcode.ORR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 13: + throw new RuntimeException("This is actually a multiply instruction."); + + case 14: + opcode = Opcode.BIC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 15: + opcode = Opcode.MVN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + default: + throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + } - case 4: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); - break; - - case 5: - opcode = Opcode.ADC; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 6: - opcode = Opcode.SBC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 7: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); - break; - - case 8: - opcode = Opcode.TST; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 9: - opcode = Opcode.RSB; - operand2 = OperandWrapper.createImmediate(0); - break; - - case 10: - opcode = Opcode.CMP; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 11: - opcode = Opcode.CMN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 12: - opcode = Opcode.ORR; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 13: - throw new RuntimeException("This is actually a multiply instruction."); - - case 14: - opcode = Opcode.BIC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 15: - opcode = Opcode.MVN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - default: - throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + Rn = finalRn; } - - Rn = finalRn; } } } @@ -692,6 +766,67 @@ /** @see #getRd() */ protected final byte Rd; + + public SingleDataTransfer(short instr) { + + writeBack = false; + preIndexing = true; + forceUserMode = false; + positiveOffset = true; + + if (Utils.getBits(instr, 11, 15) == 0x9 || + Utils.getBits(instr, 12, 15) == 0x9) { + //load from literal pool or stack load/store + Rd = (byte) Utils.getBits(instr, 8, 10); + offset = OperandWrapper.createImmediate(instr & 0xFF); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + size = TransferSize.Word; + Rn = (byte)(Utils.getBit(instr, 15) ? ARM_Registers.SP : ARM_Registers.PC); + } + else { + //load/store register offset, load/store byte/word immediate offset or load/store halfword immediate offset + Rd = (byte)Utils.getBits(instr, 0, 2); + Rn = (byte)Utils.getBits(instr, 3, 5); + + if (Utils.getBits(instr, 13, 15) == 0x5) { + //load store register offset + offset = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); + + if (Utils.getBit(instr, 9)) { + //load store byte/halfword + signExtend = Utils.getBit(instr, 10); + isLoad = signExtend || Utils.getBit(instr, 11); + + if (!signExtend) + size = TransferSize.HalfWord; + else + size = Utils.getBit(instr, 11) ? TransferSize.HalfWord : TransferSize.Byte; + } + else { + //load store byte/word + size = Utils.getBit(instr, 10) ? TransferSize.Byte : TransferSize.Word; + isLoad = Utils.getBit(instr, 11); + signExtend = false; + } + } + else { + //load/store word/halfword/byte with immediate offset + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + + if (Utils.getBit(instr, 13)) { + //transfer word/byte + size = Utils.getBit(instr, 12) ? TransferSize.Byte : TransferSize.Word; + } + else { + //transfer Half-word + size = TransferSize.HalfWord; + } + } + } + } public SingleDataTransfer(int instr) { super(instr); @@ -934,6 +1069,38 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; + + public BlockDataTransfer(short instr) { + forceUser = false; + writeBack = true; + isLoad = Utils.getBit(instr, 11); + incrementBase = postIndexing = isLoad; + + int regList = instr & 0xFF; + + if (Utils.getBit(instr, 14)) { + //PUSH / POP registers + baseRegister = ARM_Registers.SP; + + if (Utils.getBit(instr, 8)) { + //this is a procedure entry/return + if (isLoad) { + //procedure return, load pc + regList |= (1 << ARM_Registers.PC); + } + else { + //procedure entry, push lr + regList |= (1 << ARM_Registers.LR); + } + } + } + else { + //LDMIA/STMIA + baseRegister = (byte)Utils.getBits(instr, 8, 10); + } + + registerList = regList; + } public BlockDataTransfer(int instr) { super(instr); @@ -1026,6 +1193,23 @@ /** @see #getOffset() */ protected final int offset; + + public Branch(short instr) { + super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); + + if (Utils.getBit(instr, 13)) { + offset = instr & 0xFF; + link = false; + } + else { + offset = Utils.getBits(instr, 0, 10); + link = Utils.getBit(instr, 12); + + //only the second instruction of a long branch is actually a branch + if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); + } + + } public Branch(int instr) { super(instr); @@ -1057,6 +1241,19 @@ /** @see #link() */ protected final boolean link; + + public BranchExchange(short instr) { + + if (Utils.getBit(instr, 15)) { + link = true; + target = OperandWrapper.createRegisterOffset(ARM_Registers.LR, Utils.getBits(instr, 0, 10)); + } + else { + link = Utils.getBit(instr, 7); + int register = Utils.getBits(instr, 3, 6); + target = OperandWrapper.createRegister((byte)register); + } + } public BranchExchange(int instr) { super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); @@ -1072,7 +1269,7 @@ if (Utils.getBit(instr, 24)) jumpTarget += 2; - target = OperandWrapper.createPcRelative(jumpTarget); + target = OperandWrapper.createRegisterOffset(ARM_Registers.PC, jumpTarget); } else { link = Utils.getBit(instr, 5); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) @@ -40,10 +40,18 @@ /** Decodes the instruction at the given address.*/ public Instruction decode(int pc) { - - int binaryInstruction = ps.memory.loadInstruction32(pc); - ARM_Instruction instruction = ARM_InstructionDecoder.decode(binaryInstruction, instructionFactory); + ARM_Instruction instruction; + + if ((pc & 1) != 0) { + short binaryInstruction = (short)ps.memory.loadInstruction16(pc & 0xFFFFFFFE); + instruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction, instructionFactory); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(pc); + instruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction, instructionFactory); + } + if (instruction.getCondition() != Condition.AL) { return new ConditionalDecorator(instruction); } @@ -56,7 +64,6 @@ return instructionFactory.toString(); } - private abstract static class ResolvedOperand { protected int value; @@ -99,11 +106,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -111,10 +118,15 @@ value = resolveShift(regs, operand); return; - case PcRelative: - value = regs.get(ARM_Registers.PC) + 8 + operand.getOffset(); - break; + case RegisterOffset: + if (operand.getRegister() == ARM_Registers.PC) + value = regs.readPC(); + else + value =regs.get(operand.getRegister()); + value += operand.getOffset(); + return; + default: throw new RuntimeException("Unexpected wrapped operand type: " + operand.getType()); @@ -128,11 +140,11 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); - //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -213,11 +225,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -225,7 +237,7 @@ value = resolveShift(regs, operand); return; - case PcRelative: + case RegisterOffset: throw new RuntimeException("This operand type does not produce a shifter carry out."); default: @@ -241,11 +253,13 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); + int value; //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -454,7 +468,7 @@ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.get(i.Rn) + 8; + return regs.readPC(); } return regs.get(i.Rn); @@ -585,7 +599,7 @@ /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { - + if (i.updateConditionCodes) { if (i.Rd != 15) { regs.setFlags(result < 0, result == 0, shifterCarryOut); @@ -1038,7 +1052,7 @@ //also transfer the program counter, if requested so if (transferPC) { nextAddress += 4; - ps.memory.store32(nextAddress, regs.get(15) + 8); + ps.memory.store32(nextAddress, regs.readPC()); } } @@ -1096,14 +1110,14 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } else { if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, BranchType.DIRECT_BRANCH); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); } } @@ -1128,8 +1142,8 @@ public void execute() { //remember the previous address - int previousAddress = regs.get(ARM_Registers.PC) + 8; + //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? boolean thumb; @@ -1137,7 +1151,14 @@ int targetAddress; switch (i.target.getType()) { - case PcRelative: + case RegisterOffset: + int previousAddress; + + if (i.target.getRegister() == ARM_Registers.PC) + previousAddress = regs.readPC(); + else + previousAddress = regs.get(i.target.getRegister()); + targetAddress = previousAddress + i.target.getOffset(); thumb = true; break; @@ -1155,7 +1176,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, previousAddress - 4); + regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); } else { @@ -1173,7 +1194,7 @@ public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.PcRelative) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1421,11 +1442,13 @@ private int resolveAddress() { //acquire the base address - int base = regs.get(i.Rn); + int base; //take ARM's PC offset into account - if (i.Rn == 15) - base += 8; + if (i.Rn == ARM_Registers.PC) + base = regs.readPC(); + else + base = regs.get(i.Rn); //if we are not pre-indexing, then just use the base register for the memory access if (!i.preIndexing) @@ -1688,78 +1711,103 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); } public ARM_Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(new ARM_Instructions.Branch(instr)); } public ARM_Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } public ARM_Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Instruction type not supported by thumb."); } public ARM_Instruction createCoprocess... [truncated message content] |
From: <mic...@us...> - 2007-06-18 17:06:44
|
Revision: 133 http://svn.sourceforge.net/pearcolator/?rev=133&view=rev Author: michael_baer Date: 2007-06-18 10:06:44 -0700 (Mon, 18 Jun 2007) Log Message: ----------- First version that runs libc "Hello World" in Thumb code Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/DBT_Options.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = false; + public final static boolean buildForSunVM = true; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; @@ -102,7 +102,7 @@ public static boolean debugTranslation = true; /** In ProcessSpace, print syscall numbers. */ - public static boolean debugSyscall = false; + public static boolean debugSyscall = true; /** In ProcessSpace, print syscall numbers. */ public static boolean debugSyscallMore = false; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; -import org.binarytranslator.generic.os.process.ProcessSpace; /** * This class transfers an ARM instruction into a human-readable assembly @@ -54,7 +53,7 @@ decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); } - DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + DisassemblingVisitor disassembler = new DisassemblingVisitor(); decodedInstruction.visit(disassembler); return disassembler.result; @@ -130,17 +129,9 @@ /** This field receives the disassembled instruction. */ private ARM_DisassembledInstruction result; - /** The address of the instruction which is currently decoded or -1, if that address is not known. */ - private int address; - private DisassemblingVisitor() { - this.address = -1; } - private DisassemblingVisitor(int address) { - this.address = address; - } - /** Wraps a decoded assembly statement within an {@link ARM_DisassembledInstruction} object and * stores it as the result of this operation. */ private void setResult(String assembly) { @@ -180,10 +171,7 @@ op.getShiftAmount()); case RegisterOffset: - if (address != -1) - return String.format("#0x%x", op.getOffset() + address + 8); - else - return String.format("#<%d + pc>", op.getOffset()); + return String.format("#<r%d + %d>", op.getRegister(), op.getOffset()); case Register: return "r" + op.getRegister(); @@ -361,11 +349,7 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - - if (address != -1) - setResult(String.format("%s%s #%d", mnemonic, cond(instr), instr.getOffset() + address + 8)); - else - setResult(String.format("%s%s #<%d + pc>", mnemonic, cond(instr), instr.getOffset())); + setResult(String.format("%s%s [PC + %s]", mnemonic, cond(instr), operand(instr.offset))); } public void visit(BranchExchange instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-18 17:06:44 UTC (rev 133) @@ -336,10 +336,14 @@ } else { //bit8==bit9==bit10==1? - if ((instr & 0x70) == 0x70) + if ((instr & 0x700) == 0x700) return factory.createBranchExchange(instr); - return factory.createDataProcessing(instr); + //We're not treating multiplication as data processing + if (Utils.getBits(instr, 6, 10) == 13) + return factory.createIntMultiply(instr); + else + return factory.createDataProcessing(instr); } } } @@ -361,20 +365,15 @@ @Override <T> T decode(short instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 11)) { - return factory.createSingleDataTransfer(instr); + //bit9==bit10==bit11==1? + if ((instr & 0x0E00) == 0x0E00) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); } - else { - //bit9==bit10==bit11==1? - if ((instr & 0xE0) == 0xE0) { - if (Utils.getBit(instr, 8)) - return factory.createSoftwareInterrupt(instr); - else - return factory.createUndefinedInstruction(instr); - } - - return factory.createBranch(instr); - } + + return factory.createBranch(instr); } } @@ -424,7 +423,7 @@ */ static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { - int bits_12_15 = Utils.getBits(instruction, 12, 15); + int bits_12_15 = (instruction & 0xF000) >>> 12; return prefixDecoders[bits_12_15].decode(instruction, factory); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-18 17:06:44 UTC (rev 133) @@ -22,6 +22,8 @@ /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { + protected final boolean isThumb; + public enum Condition { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV } @@ -31,15 +33,22 @@ private Instruction () { this.condition = Condition.AL; + this.isThumb = true; } private Instruction (Condition condition) { this.condition = condition; + this.isThumb = true; } private Instruction(int instr) { condition = Condition.values()[(instr & 0xF0000000) >>> 28]; + this.isThumb = false; } + + public final int size() { + return isThumb ? 2 : 4; + } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ public final Condition getCondition() { @@ -54,69 +63,6 @@ /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ public abstract void visit(ARM_InstructionVisitor visitor); } - - /** Base class for multiply operations. */ - protected abstract static class MultiplyTemplate extends Instruction { - - /** @see #updateConditionCodes() */ - protected final boolean updateConditionCodes; - - /** @see #accumulate() */ - protected final boolean accumulate; - - /** @see #getRs() */ - protected final byte Rs; - - /** @see #getRn() */ - protected final byte Rn; - - /** @see #getRm() */ - protected final byte Rm; - - /** @see #getRd() */ - protected final byte Rd; - - protected MultiplyTemplate(int instr) { - super(instr); - - updateConditionCodes = Utils.getBit(instr, 20); - accumulate = Utils.getBit(instr, 21); - Rd = (byte) Utils.getBits(instr, 16, 19); - Rn = (byte) Utils.getBits(instr, 12, 15); - Rs = (byte) Utils.getBits(instr, 8, 11); - Rm = (byte) Utils.getBits(instr, 0, 3); - } - - /** Returns true, if the condition codes shall be updated by the result of this operation. */ - public final boolean updateConditionCodes() { - return updateConditionCodes; - } - - /** Returns true, if this is the accumulate version of the instruction. */ - public final boolean accumulate() { - return accumulate; - } - - /** Returns the register number of the Rs operand register. */ - public final byte getRs() { - return Rs; - } - - /** Returns the register number of the Rm operand register. */ - public final byte getRm() { - return Rm; - } - - /** Returns the register number of the Rn operand register. */ - public final byte getRn() { - return Rn; - } - - /** Returns the register number of the Rd destination register. */ - public final byte getRd() { - return Rd; - } - } /** Base class for coprocessor instructions. */ protected static abstract class CoprocessorTemplate extends Instruction { @@ -473,7 +419,7 @@ updateConditionCodes = false; Rd = (byte)Utils.getBits(instr, 8, 10); Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); - operand2 = OperandWrapper.createImmediate(instr & 0xFF); + operand2 = OperandWrapper.createImmediate((instr & 0xFF) << 2); return; } @@ -484,12 +430,12 @@ opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; Rd = (byte)ARM_Registers.SP; Rn = (byte)ARM_Registers.SP; - operand2 = OperandWrapper.createImmediate(instr & 0x7F); + operand2 = OperandWrapper.createImmediate((instr & 0x7F) << 2); return; } - if (Utils.getBits(instr, 14, 15) == 0x7) { + if (Utils.getBits(instr, 13, 15) == 0x7) { //first instruction of a long bl/blx if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); @@ -512,7 +458,7 @@ Rn = (byte)Utils.getBits(instr, 3, 5); updateConditionCodes = true; - if (Utils.getBits(instr, 11, 12) == 0) { + if (Utils.getBits(instr, 11, 12) != 0x3) { //shift by immediate opcode = Opcode.MOV; ShiftType type = ShiftType.values()[Utils.getBits(instr, 11, 12)]; @@ -559,19 +505,21 @@ Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); Rn = Rd; operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); - updateConditionCodes = true; switch (Utils.getBits(instr, 8, 9)) { case 0: opcode = Opcode.ADD; + updateConditionCodes = false; break; case 1: opcode = Opcode.CMP; + updateConditionCodes = true; break; case 2: opcode = Opcode.MOV; + updateConditionCodes = false; break; case 3: @@ -631,6 +579,7 @@ case 8: opcode = Opcode.TST; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 9: @@ -641,11 +590,13 @@ case 10: opcode = Opcode.CMP; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 11: opcode = Opcode.CMN; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 12: @@ -778,7 +729,7 @@ Utils.getBits(instr, 12, 15) == 0x9) { //load from literal pool or stack load/store Rd = (byte) Utils.getBits(instr, 8, 10); - offset = OperandWrapper.createImmediate(instr & 0xFF); + offset = OperandWrapper.createImmediate((instr & 0xFF) * 4); isLoad = Utils.getBit(instr, 11); signExtend = false; size = TransferSize.Word; @@ -812,7 +763,6 @@ } else { //load/store word/halfword/byte with immediate offset - offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); isLoad = Utils.getBit(instr, 11); signExtend = false; @@ -824,6 +774,23 @@ //transfer Half-word size = TransferSize.HalfWord; } + + switch (size) { + case Word: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 2); + break; + + case HalfWord: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 1); + break; + + case Byte: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + break; + + default: + throw new RuntimeException("Unexpected transfer size."); + } } } } @@ -947,23 +914,105 @@ } /** Represents a normal (not long) multiply instruction. */ - public final static class IntMultiply extends MultiplyTemplate { + public final static class IntMultiply extends Instruction { + + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte Rd; + + protected IntMultiply(short instr) { + updateConditionCodes = true; + accumulate = false; + Rd = (byte)Utils.getBits(instr, 0, 2); + Rm = (byte)Utils.getBits(instr, 3, 5); + Rn = Rd; + Rs = Rd; + } protected IntMultiply(int instr) { super(instr); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + Rd = (byte) Utils.getBits(instr, 16, 19); + Rn = (byte) Utils.getBits(instr, 12, 15); + Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); + //check for instruction combinations that show undefined behaviour on ARM if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } + + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public final boolean updateConditionCodes() { + return updateConditionCodes; + } + /** Returns true, if this is the accumulate version of the instruction. */ + public final boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public final byte getRs() { + return Rs; + } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + + /** Returns the register number of the Rn operand register. */ + public final byte getRn() { + return Rn; + } + + /** Returns the register number of the Rd destination register. */ + public final byte getRd() { + return Rd; + } + public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } } /** Represents a long multiply instruction. */ - public final static class LongMultiply extends MultiplyTemplate { + public final static class LongMultiply extends Instruction { + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + /** @see #getRn() */ + protected final byte RdLow; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte RdHigh; + /** @see #isUnsigned() */ protected final boolean unsigned; @@ -971,19 +1020,45 @@ super(instr); unsigned = Utils.getBit(instr, 22); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + RdHigh = (byte) Utils.getBits(instr, 16, 19); + RdLow = (byte) Utils.getBits(instr, 12, 15); + Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); //check for instruction combinations that show undefined behaviour on ARM - if (DBT.VerifyAssertions) DBT._assert(Rd != 15); + if (DBT.VerifyAssertions) DBT._assert(RdHigh != 15 && RdLow != 15); } + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public final boolean updateConditionCodes() { + return updateConditionCodes; + } + + /** Returns true, if this is the accumulate version of the instruction. */ + public final boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public final byte getRs() { + return Rs; + } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ public final byte getRdHigh() { - return Rd; + return RdHigh; } /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ public final byte getRdLow() { - return Rn; + return RdLow; } /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ @@ -1074,11 +1149,12 @@ forceUser = false; writeBack = true; isLoad = Utils.getBit(instr, 11); - incrementBase = postIndexing = isLoad; int regList = instr & 0xFF; - if (Utils.getBit(instr, 14)) { + if (!Utils.getBit(instr, 14)) { + incrementBase = postIndexing = isLoad; + //PUSH / POP registers baseRegister = ARM_Registers.SP; @@ -1097,6 +1173,7 @@ else { //LDMIA/STMIA baseRegister = (byte)Utils.getBits(instr, 8, 10); + incrementBase = postIndexing = true; } registerList = regList; @@ -1192,19 +1269,23 @@ protected final boolean link; /** @see #getOffset() */ - protected final int offset; + protected final OperandWrapper offset; public Branch(short instr) { - super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); - - if (Utils.getBit(instr, 13)) { - offset = instr & 0xFF; + super (Utils.getBit(instr, 13) ? Condition.AL : Condition.values()[Utils.getBits(instr, 8, 11)]); + + if (!Utils.getBit(instr, 13)) { + offset = OperandWrapper.createImmediate(Utils.signExtend(instr & 0xFF, 8) << 1); link = false; } else { - offset = Utils.getBits(instr, 0, 10); link = Utils.getBit(instr, 12); + if (link) + offset = OperandWrapper.createRegisterOffset(link ? ARM_Registers.LR : ARM_Registers.PC, (Utils.getBits(instr, 0, 10) << 1) - 2); + else + offset = OperandWrapper.createImmediate(Utils.signExtend(Utils.getBits(instr, 0, 10), 11) << 1); + //only the second instruction of a long branch is actually a branch if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); } @@ -1214,7 +1295,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = Utils.signExtend((instr & 0xFFFFFF) << 2, 26); + offset = OperandWrapper.createImmediate(Utils.signExtend((instr & 0xFFFFFF) << 2, 26)); } /** Should the current PC be put into the lr? */ @@ -1223,7 +1304,7 @@ } /** The offset of the target address to the PC */ - public final int getOffset() { + public final OperandWrapper getOffset() { return offset; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-18 17:06:44 UTC (rev 133) @@ -374,21 +374,25 @@ public void execute() { if (isConditionTrue()) { + int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); conditionalInstruction.execute(); - int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); - if (nextInstruction != -1) ps.setCurrentInstructionAddress(nextInstruction); } - else - ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress()+4); + else { + ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + (regs.getThumbMode() ? 2 : 4)); + } } public int getSuccessor(int pc) { //if this instruction is not a jump, then we can tell what the next instruction will be. - if (conditionalInstruction.getSuccessor(pc) == pc + 4) - return pc + 4; + + int conditionalSuccessor = conditionalInstruction.getSuccessor(pc); + boolean thumbMode = (pc & 0x1) == 1; + + if (conditionalSuccessor == pc + 4 && !thumbMode) + return conditionalSuccessor; //ARM may have conditional non-jump instructions else return -1; } @@ -463,12 +467,22 @@ protected DataProcessing(ARM_Instructions.DataProcessing instr) { i = instr; } + + @Override + public String toString() { + return i.toString(); + } /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.readPC(); + int value = regs.readPC(); + + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + value = value & 0xFFFFFFFC; + + return value; } return regs.get(i.Rn); @@ -551,7 +565,7 @@ public int getSuccessor(int pc) { if (i.Rd != 15) - return pc + 4; + return pc + i.size(); else return -1; } @@ -925,11 +939,16 @@ regs.set(i.Rd, tmp); } } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //according to the ARM Architecture reference, using the pc as Rd yields an undefined //result. Therefore, we can safely assume that this instruction never equals a branch - return pc + 4; + return pc + i.size(); } } @@ -1036,7 +1055,7 @@ } else { //shall we switch to thumb mode - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + regs.set(ARM_Registers.PC, newpc); regs.setThumbMode((newpc & 0x1) != 0); } } @@ -1062,7 +1081,7 @@ ps.registers.switchOperatingMode(previousMode); } - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { //write the last address we read from back to a register if (!i.incrementBase) { //backward reading @@ -1089,12 +1108,17 @@ return i.condition; } + @Override + public String toString() { + return i.toString(); + } + public int getSuccessor(int pc) { //if we're loading values into the PC, then we can't tell where this instruction will be going if (i.isLoad && transferPC) return -1; else - return pc + 4; + return pc + i.size(); } } @@ -1108,25 +1132,53 @@ } public void execute() { + + int destination; + BranchType branchType; + + if (i.offset.getType() != OperandWrapper.Type.Immediate) { + branchType = BranchType.INDIRECT_BRANCH; + } + else { + branchType = BranchType.DIRECT_BRANCH; + } + + destination = regs.readPC() + ResolvedOperand.resolve(regs, i.offset); + + if (DBT_Options.profileDuringInterpretation) { + if (i.link) { + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), destination, regs.get(ARM_Registers.PC) + i.size()); + } + else { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), destination, branchType); + } + } + //if we're supposed to link, then write the previous address into the link register if (i.link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); - - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } - else { - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); - } + + if (regs.getThumbMode()) + destination |= 1; + + regs.set(ARM_Registers.PC, destination); } public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + i.getOffset() + 8; + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return (pc + 2*i.size() + i.getOffset().getImmediate()) | (pc & 1); + else + return -1; } } @@ -1164,9 +1216,13 @@ break; case Register: - targetAddress = regs.get(i.target.getRegister()); + if (i.target.getRegister() != ARM_Registers.PC) + targetAddress = regs.get(i.target.getRegister()); + else + targetAddress = regs.readPC(); + thumb = (targetAddress & 0x1) != 0; - targetAddress = targetAddress & 0xFFFFFFFE; + //targetAddress = targetAddress & 0xFFFFFFFE; break; default: @@ -1177,7 +1233,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), targetAddress, regs.get(ARM_Registers.PC) + i.size()); } else { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); @@ -1191,10 +1247,15 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset && i.target.getRegister() == ARM_Registers.PC) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1238,9 +1299,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1293,9 +1359,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1319,13 +1390,18 @@ } } + @Override + public String toString() { + return i.toString(); + } + public Condition getCondition() { return i.condition; } public int getSuccessor(int pc) { //Rd should never be the PC, so we can safely predict the next instruction - return pc + 4; + return pc + i.size(); } } @@ -1389,9 +1465,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc+4; + return pc + i.size(); } } @@ -1411,6 +1492,11 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { return -1; @@ -1445,8 +1531,13 @@ int base; //take ARM's PC offset into account - if (i.Rn == ARM_Registers.PC) + if (i.Rn == ARM_Registers.PC) { base = regs.readPC(); + + //Thumb mode has this weird way of accessing the PC sometimes + if (i.isThumb && i.isLoad) + base = base & 0xFFFFFFFC; + } else base = regs.get(i.Rn); @@ -1504,7 +1595,7 @@ regs.set(i.Rd, value); if (DBT_Options.profileDuringInterpretation) { - if (i.Rd == 15) + if (i.Rd == ARM_Registers.PC) ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); } } @@ -1551,13 +1642,18 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're loading to the PC, then the next instruction is undefined if (i.Rd == ARM_Registers.PC && i.isLoad) return -1; - return pc + 4; + return pc + i.size(); } } @@ -1582,6 +1678,12 @@ } private final class DebugNopInstruction implements ARM_Instruction { + + private boolean isThumb; + + public DebugNopInstruction(boolean isThumb) { + this.isThumb = isThumb; + } public void execute() { } @@ -1591,7 +1693,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + (isThumb ? 2 : 4); } } @@ -1661,21 +1763,21 @@ //TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createIntMultiply(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-18 17:06:44 UTC (rev 133) @@ -1686,7 +1686,7 @@ } private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(i.baseRegister); //write the last address we read from back to a register @@ -1737,20 +1737,38 @@ } public void translate() { + + if (i.offset.getType() == OperandWrapper.Type.Immediate) { + //we can directly resolve this branch to a fixed address + if (i.link) + arm2ir.appendCall( readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); + else + arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); + } + else { + + OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); + OPT_RegisterOperand dest = arm2ir.getTempInt(0); + + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); + + if (i.link) { + arm2ir.appendCall(dest, lazy, pc + i.size()); + } + else { + arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); + } + } //if we're supposed to link, then write the previous address into the link register - if (i.link) { + if (i.link) { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); } else { //we should never be returning from the goto arm2ir.getCurrentBlock().deleteNormalOut(); } - - if (i.link) - arm2ir.appendCall( readPC() + i.getOffset(), lazy, pc + 4); - else - arm2ir.appendBranch(readPC() + i.getOffset(), lazy, BranchType.DIRECT_BRANCH); + } public Condition getCondition() { @@ -1758,7 +1776,10 @@ } public int getSuccessor(int pc) { - return readPC() + i.getOffset(); + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return readPC() + i.getOffset().getImmediate(); + else + return -1; } } @@ -2086,6 +2107,13 @@ //add the offset to the base register OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset())); + + if (i.isThumb && i.isLoad && i.Rn == ARM_Registers.PC) { + //with thumb, bit 1 of the address is always ignored - address = address & 0xFFFFFFFC; + //see ARM reference manual for further details + arm2ir.appendInstruction(Binary.create(INT_AND, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(0xFFFFFFFC))); + } + return tmp.copy(); } Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-18 17:06:44 UTC (rev 133) @@ -53,7 +53,7 @@ */ static final int getBits(short word, int from, int to) { if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to < 15); + DBT._assert(from < to && from >= 0 && to <= 15); return (word & ((1 << (to + 1)) - 1)) >> from; } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-18 17:06:44 UTC (rev 133) @@ -289,11 +289,13 @@ * or 4 (Thumb) to the program counter itself. */ public int readPC() { - if (getThumbMode()) { - return get(ARM_Registers.PC) + 4; + int pc = get(ARM_Registers.PC); + + if ((pc & 0x1) == 1) { + return (pc & 0xFFFFFFFE) + 4; } else { - return get(ARM_Registers.PC) + 8; + return pc + 8; } } @@ -377,7 +379,7 @@ * Processor in thumb mode? */ public boolean getThumbMode() { - return thumbMode; + return thumbMode || ((get(ARM_Registers.PC) & 1) != 0); } /** Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-18 17:06:44 UTC (rev 133) @@ -28,7 +28,9 @@ ARM_Instructions.Instruction instr; if (registers.getThumbMode()) { - short instruction = (short)memory.loadInstruction16(getCurrentInstructionAddress()); + int instrAddr = getCurrentInstructionAddress() & 0xFFFFFFFE; + System.out.println("Thumb syscall at: " + instrAddr); + short instruction = (short)memory.loadInstruction16(instrAddr); instr = ARM_InstructionDecoder.Thumb.decode(instruction); } else { @@ -44,11 +46,11 @@ //Use a mask to let both calls start from the same address int sysCallNr = ((ARM_Instructions.SoftwareInterrupt)instr).getInterruptNumber(); - if (sysCallNr == 0x123456) { + if (sysCallNr == 0x123456 || sysCallNr == 0xab) { sysCalls.doSysCall(registers.get(0)); //simulate a proper return from syscalls - setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); + setCurrentInstructionAddress(getCurrentInstructionAddress() + instr.size()); } else { //switch the operating mode to Supervisor Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-18 17:06:44 UTC (rev 133) @@ -18,7 +18,7 @@ while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); - //System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); + System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); pc = instruction.getSuccessor(pc); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-04 15:17:38
|
Revision: 145 http://svn.sourceforge.net/pearcolator/?rev=145&view=rev Author: michael_baer Date: 2007-07-04 08:17:39 -0700 (Wed, 04 Jul 2007) Log Message: ----------- - Added support for IfCmp branches to a target address. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-04 15:17:39 UTC (rev 145) @@ -833,8 +833,8 @@ default: throw new RuntimeException("Unexpected condition code: " + condition); - } - + } + arm2ir.setCurrentBlock(condBlock); conditionalInstruction.translate(); } @@ -1773,7 +1773,7 @@ } else { //just branch and never return from it - arm2ir.appendBranch(destination, lazy, BranchType.DIRECT_BRANCH); + arm2ir.appendBranch(destination, lazy); arm2ir.getCurrentBlock().deleteNormalOut(); } } @@ -1798,7 +1798,6 @@ arm2ir.getCurrentBlock().deleteNormalOut(); } } - } public Condition getCondition() { Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-04 15:17:39 UTC (rev 145) @@ -11704,7 +11704,7 @@ } if (LK == 0) - ppc2ir.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(target_address, lazy); else ppc2ir.appendCall(target_address, lazy, pc + 4); @@ -11727,7 +11727,7 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendBranch(pc + 4, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(pc + 4, lazy); return target_address; } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-04 15:17:39 UTC (rev 145) @@ -4035,7 +4035,7 @@ translationHelper.appendInstruction(gotoInstr); translationHelper.setCurrentBlock(executeBranch); - translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy); translationHelper.setCurrentBlock(fallThrough); return pc + length; @@ -4169,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy); } else { int operandSize; if (prefix3 == null) { Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-04 15:17:39 UTC (rev 145) @@ -34,6 +34,7 @@ import org.jikesrvm.compilers.opt.ir.Call; import org.jikesrvm.compilers.opt.ir.Goto; import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.IfCmp2; import org.jikesrvm.compilers.opt.ir.LookupSwitch; import org.jikesrvm.compilers.opt.ir.Move; import org.jikesrvm.compilers.opt.ir.New; @@ -559,13 +560,25 @@ * The address where we shall jump to. * @param targetLaziness * The current at the point of jump. - * @param branchType - * The type of branch that best describes this jump. */ - public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { + public void appendBranch(int targetPC, Laziness targetLaziness) { + + appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); + } + + /** + * Appends the conditional branch instruction <code>conditional</code> that jumps to the address + * <code>targetPc</code> to the current block. + * + * @param targetPC + * The address where we shall jump to. + * @param targetLaziness + * The current at the point of jump. + */ + public void appendConditionalBranch(OPT_Instruction conditional, int targetPC, Laziness targetLaziness) { - if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); - appendStaticBranch(targetPC, targetLaziness, branchType, -1); + if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(conditional) || IfCmp2.conforms(conditional)); + appendStaticBranch(conditional, targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); } /** @@ -582,16 +595,15 @@ */ public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { - appendStaticBranch(targetPC, targetLaziness, BranchType.CALL, retAddr); + appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.CALL, retAddr); } - private void appendStaticBranch(int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { + private void appendStaticBranch(OPT_Instruction branch, int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { // Place a GOTO instruction at this point. However, this instruction // serves more as a placeholder and might be mutated later on. - OPT_Instruction jump = Goto.create(GOTO, null); - appendInstruction(jump); + appendInstruction(branch); UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - jump, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); + branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); if (branchType == BranchType.CALL) @@ -677,10 +689,6 @@ int targetPc = unresolvedInstr.targetPC; Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; OPT_Instruction gotoInstr = unresolvedInstr.instruction; - - if (DBT.VerifyAssertions) - DBT._assert(Goto.conforms(gotoInstr)); - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); if (DBT_Options.debugBranchResolution) { @@ -688,13 +696,32 @@ + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } - // Fix up instruction - Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); + // Fix up instruction + setBranchTarget(gotoInstr, targetBB.makeJumpTarget()); gotoInstr.getBasicBlock().insertOut(targetBB); } } /** + * Sets the target of the branching instruction <code>branch</code> to <code>target</code>. + * @param branch + * A branching instruction. Either a Goto or + * @param target + * The jump target. + */ + private void setBranchTarget(OPT_Instruction branch, OPT_BranchOperand target) { + if (Goto.conforms(branch)) { + Goto.setTarget(branch, target); + } + else if (IfCmp.conforms(branch)) { + IfCmp.setTarget(branch, target); + } + else if (IfCmp2.conforms(branch)) { + IfCmp2.setTarget1(branch, target); + } + } + + /** * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when * the jump target is not part of the current trace anyway. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-06 10:39:24
|
Revision: 147 http://svn.sourceforge.net/pearcolator/?rev=147&view=rev Author: michael_baer Date: 2007-07-06 03:39:15 -0700 (Fri, 06 Jul 2007) Log Message: ----------- Renamed BranchLogic to BranchProfile Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/ExecutionController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/branchprofile/ src/org/binarytranslator/generic/branchprofile/BranchProfile.java src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java Removed Paths: ------------- src/org/binarytranslator/generic/branch/ src/org/binarytranslator/generic/branchprofile/BranchLogic.java src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/DBT_Options.java 2007-07-06 10:39:15 UTC (rev 147) @@ -21,7 +21,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/Main.java 2007-07-06 10:39:15 UTC (rev 147) @@ -107,7 +107,7 @@ //on SUN's VM, only the interpreter has been tested if (DBT_Options.buildForSunVM) { - DBT_Options.executionController = ExecutionController.Type.PredecodingThreadedInterpreter; + DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter; } @@ -116,7 +116,7 @@ switch (DBT_Options.executionController) { - case PredecodingThreadedInterpreter: + case PredecodingInterpreter: controller = new PredecodingThreadedInterpreter(ps); //new PredecodingThreadedInterpreter(ps); break; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-06 10:39:15 UTC (rev 147) @@ -9,7 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.decoder.Utils; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-06 10:39:15 UTC (rev 147) @@ -9,7 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Method; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) @@ -11,8 +11,8 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; -import org.binarytranslator.generic.branch.BranchLogic; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; @@ -4026,7 +4026,7 @@ branchAddress = ppc2ir.getLRRegister(); } - ppc2ir.appendBranch(branchAddress, lazy, BranchLogic.BranchType.RETURN); + ppc2ir.appendBranch(branchAddress, lazy, BranchProfile.BranchType.RETURN); // stop translation on branch always if (BO == 0x14) { Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) @@ -11,7 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; Copied: src/org/binarytranslator/generic/branchprofile (from rev 133, src/org/binarytranslator/generic/branch) Deleted: src/org/binarytranslator/generic/branchprofile/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/BranchLogic.java 2007-07-06 10:39:15 UTC (rev 147) @@ -1,318 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.branch; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -/** - * Object capturing branches and jumps so that traces can avoid terminating on - * branches whose destinations aren't known - */ -public class BranchLogic { - - public enum BranchType { - INDIRECT_BRANCH, - DIRECT_BRANCH, - CALL, - RETURN - } - - /** A set of procedure information */ - private final SortedMap<Integer, ProcedureInformation> procedures; - - /** A set of switch like branchs sites and their destinations */ - private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations; - - /** Global branch information */ - private static BranchLogic global; - - /** - * Constructor has 2 functions: (1) when making a local trace we don't want to - * consider as many procedure return points as may be known for the full - * program. (2) making sure switch like branches are all recorded globally - */ - public BranchLogic() { - if (global == null) { - global = this; - branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>(); - } - else { - branchSitesAndDestinations = global.branchSitesAndDestinations; - } - procedures = new TreeMap<Integer, ProcedureInformation>(); - } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param dest - * the destination of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerCall(int pc, int dest, int ret) { - ProcedureInformation procedure = procedures.get(dest); - - if (procedure != null) { - procedure.registerCall(pc, ret); - } else { - procedure = new ProcedureInformation(pc, ret, dest); - procedures.put(dest, procedure); - } - - registerBranch(pc, dest); - } - - /** - * Register a function return. - * - * @param pc - * the address of the branch instruction - * @param lr - * the return address (value of the link register) - */ - public void registerReturn(int pc, int lr) { - - ProcedureInformation procedure = getLikelyProcedure(pc); - - if (procedure != null) { - procedure.registerReturn(pc, lr); - } - - registerBranch(pc, lr); - } - - /** - * Given an address within a procedure, returns the (most likely) procedure - * - * @param pc - * a location within the procedure - * @return corressponding procedure information - */ - private ProcedureInformation getLikelyProcedure(int pc) { - if (procedures.size() > 0) { - SortedMap<Integer, ProcedureInformation> priorProcedures = procedures.headMap(pc); - if (priorProcedures.size() > 0) { - Integer procedureEntry = priorProcedures.lastKey(); - return procedures.get(procedureEntry); - } - } - return null; - } - - /** - * Registers a branch from the address <code>origin</code> to the address <code>target</code>. - * The type of branch is determined by <code>type</code>, which is an ordinal from the - * {@link BranchType} enum. - * - * @param origin - * The address from which the branch occurs. - * @param target - * The address to which the program is branching. - * @param type - * The most likely type of the branch. This is taken from the {@link BranchType} enum. - */ - public void registerBranch(int origin, int target, BranchType type) { - - switch (type) { - case CALL: - throw new RuntimeException("Use the more specific registerCall() for these cases."); - - case RETURN: - registerReturn(origin, target); - break; - - default: - registerBranch(origin, target); - } - } - - /** - * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. - * - * @param origin - * The address that the branch is taking place from. - * @param target - * The branch target address. - */ - private void registerBranch(int origin, int target) { - //Perform the general branch registration, too - Set<Integer> dests = branchSitesAndDestinations.get(origin); - - if (dests != null && dests.contains(target)) { - // This destination address is already registered - return; - } - else { - dests = new HashSet<Integer>(); - branchSitesAndDestinations.put(origin, dests); - } - - dests.add(target); - } - - /** - * Returns a list of known branch targets for the branch at address <code>pc</code>. - * - * @param pc - * The address where the branch originates from. - * @return - * A list of known target addresses for this branch. It is not critical to the functionality of the - * translated binary, if this list is not complete. - */ - public Set<Integer> getKnownBranchTargets(int pc) { - return branchSitesAndDestinations.get(pc); - } - - public void loadFromXML(String filename) throws IOException { - - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - Document doc; - try { - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - doc = docBuilder.parse(filename); - } catch (ParserConfigurationException e) { - throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); - } catch (SAXException e) { - throw new IOException("File " + filename + " is not a valid XML file."); - } - - if (DBT.VerifyAssertions) DBT._assert(doc != null); - - Element root = doc.getDocumentElement(); - - if (!root.getNodeName().equals("branch-profile")) - throw new IOException("File is not a valid XML branch profile."); - - Node branches = null; - - for (int i = 0; i < root.getChildNodes().getLength(); i++) { - Node node = root.getChildNodes().item(0); - - if (node.getNodeName().equals("branches")) { - branches = node; - break; - } - } - - if (branches == null) - throw new IOException("File is not a valid XML branch profile."); - - for (int i = 0; i < branches.getChildNodes().getLength(); i++) { - Node siteNode = branches.getChildNodes().item(i); - - if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) - throw new IOException("File is not a valid XML branch profile."); - - int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); - - for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { - Node target = siteNode.getChildNodes().item(n); - - if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) - throw new IOException("File is not a valid XML branch profile."); - - int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); - registerBranch(pc, targetAddress); - } - } - } - - /** - * Saves the branch profile of the current process space to the give file in XML format. - * - * @param filename - * The name of the file to which the branch profile is saved. - * @throws IOException - * Thrown if there is an error while creating the file. - */ - public void saveAsXML(String filename) throws IOException { - - FileOutputStream outputStream; - - try { - File f = new File(filename); - - if (!f.exists()) - f.createNewFile(); - - outputStream = new FileOutputStream(f); - } - catch (FileNotFoundException e) { - //this should not happen, as we just created the file - throw new IOException("Error creating file: " + filename); - } - - //Create an XML representation of the branch profile - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - try { - docBuilder = docBuilderFactory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new IOException("Error creating parser to produce XML document."); - } - Document doc = docBuilder.newDocument(); - - Element root = doc.createElement("branch-profile"); - root.setAttribute("application", DBT_Options.executableFile); - doc.appendChild(root); - - Element branchesElement = doc.createElement("branches"); - root.appendChild(branchesElement); - - for (int pc : branchSitesAndDestinations.keySet()) { - Element branchSiteElement = doc.createElement("origin"); - branchesElement.appendChild(branchSiteElement); - branchSiteElement.setAttribute("address", Integer.toString(pc)); - - for (int target : getKnownBranchTargets(pc)) { - Element branchTargetElement = doc.createElement("target"); - branchSiteElement.appendChild(branchTargetElement); - branchTargetElement.setAttribute("address", Integer.toString(target)); - } - } - - //Output the resulting XML document - TransformerFactory tFactory = TransformerFactory.newInstance(); - Transformer transformer; - try { - transformer = tFactory.newTransformer(); - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(outputStream); - transformer.transform(source, result); - - } catch (Exception e) { - e.printStackTrace(); - } - } -} Copied: src/org/binarytranslator/generic/branchprofile/BranchProfile.java (from rev 133, src/org/binarytranslator/generic/branch/BranchLogic.java) =================================================================== --- src/org/binarytranslator/generic/branchprofile/BranchProfile.java (rev 0) +++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-06 10:39:15 UTC (rev 147) @@ -0,0 +1,318 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.branchprofile; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + * Object capturing branches and jumps so that traces can avoid terminating on + * branches whose destinations aren't known + */ +public class BranchProfile { + + public enum BranchType { + INDIRECT_BRANCH, + DIRECT_BRANCH, + CALL, + RETURN + } + + /** A set of procedure information */ + private final SortedMap<Integer, ProcedureInformation> procedures; + + /** A set of switch like branchs sites and their destinations */ + private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations; + + /** Global branch information */ + private static BranchProfile global; + + /** + * Constructor has 2 functions: (1) when making a local trace we don't want to + * consider as many procedure return points as may be known for the full + * program. (2) making sure switch like branches are all recorded globally + */ + public BranchProfile() { + if (global == null) { + global = this; + branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>(); + } + else { + branchSitesAndDestinations = global.branchSitesAndDestinations; + } + procedures = new TreeMap<Integer, ProcedureInformation>(); + } + + /** + * Register a call (branch and link) instruction + * + * @param pc + * the address of the branch instruction + * @param dest + * the destination of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerCall(int pc, int dest, int ret) { + ProcedureInformation procedure = procedures.get(dest); + + if (procedure != null) { + procedure.registerCall(pc, ret); + } else { + procedure = new ProcedureInformation(pc, ret, dest); + procedures.put(dest, procedure); + } + + registerBranch(pc, dest); + } + + /** + * Register a function return. + * + * @param pc + * the address of the branch instruction + * @param lr + * the return address (value of the link register) + */ + public void registerReturn(int pc, int lr) { + + ProcedureInformation procedure = getLikelyProcedure(pc); + + if (procedure != null) { + procedure.registerReturn(pc, lr); + } + + registerBranch(pc, lr); + } + + /** + * Given an address within a procedure, returns the (most likely) procedure + * + * @param pc + * a location within the procedure + * @return corressponding procedure information + */ + private ProcedureInformation getLikelyProcedure(int pc) { + if (procedures.size() > 0) { + SortedMap<Integer, ProcedureInformation> priorProcedures = procedures.headMap(pc); + if (priorProcedures.size() > 0) { + Integer procedureEntry = priorProcedures.lastKey(); + return procedures.get(procedureEntry); + } + } + return null; + } + + /** + * Registers a branch from the address <code>origin</code> to the address <code>target</code>. + * The type of branch is determined by <code>type</code>, which is an ordinal from the + * {@link BranchType} enum. + * + * @param origin + * The address from which the branch occurs. + * @param target + * The address to which the program is branching. + * @param type + * The most likely type of the branch. This is taken from the {@link BranchType} enum. + */ + public void registerBranch(int origin, int target, BranchType type) { + + switch (type) { + case CALL: + throw new RuntimeException("Use the more specific registerCall() for these cases."); + + case RETURN: + registerReturn(origin, target); + break; + + default: + registerBranch(origin, target); + } + } + + /** + * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + private void registerBranch(int origin, int target) { + //Perform the general branch registration, too + Set<Integer> dests = branchSitesAndDestinations.get(origin); + + if (dests != null && dests.contains(target)) { + // This destination address is already registered + return; + } + else { + dests = new HashSet<Integer>(); + branchSitesAndDestinations.put(origin, dests); + } + + dests.add(target); + } + + /** + * Returns a list of known branch targets for the branch at address <code>pc</code>. + * + * @param pc + * The address where the branch originates from. + * @return + * A list of known target addresses for this branch. It is not critical to the functionality of the + * translated binary, if this list is not complete. + */ + public Set<Integer> getKnownBranchTargets(int pc) { + return branchSitesAndDestinations.get(pc); + } + + public void loadFromXML(String filename) throws IOException { + + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(filename); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); + } catch (SAXException e) { + throw new IOException("File " + filename + " is not a valid XML file."); + } + + if (DBT.VerifyAssertions) DBT._assert(doc != null); + + Element root = doc.getDocumentElement(); + + if (!root.getNodeName().equals("branch-profile")) + throw new IOException("File is not a valid XML branch profile."); + + Node branches = null; + + for (int i = 0; i < root.getChildNodes().getLength(); i++) { + Node node = root.getChildNodes().item(0); + + if (node.getNodeName().equals("branches")) { + branches = node; + break; + } + } + + if (branches == null) + throw new IOException("File is not a valid XML branch profile."); + + for (int i = 0; i < branches.getChildNodes().getLength(); i++) { + Node siteNode = branches.getChildNodes().item(i); + + if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); + + for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { + Node target = siteNode.getChildNodes().item(n); + + if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + registerBranch(pc, targetAddress); + } + } + } + + /** + * Saves the branch profile of the current process space to the give file in XML format. + * + * @param filename + * The name of the file to which the branch profile is saved. + * @throws IOException + * Thrown if there is an error while creating the file. + */ + public void saveAsXML(String filename) throws IOException { + + FileOutputStream outputStream; + + try { + File f = new File(filename); + + if (!f.exists()) + f.createNewFile(); + + outputStream = new FileOutputStream(f); + } + catch (FileNotFoundException e) { + //this should not happen, as we just created the file + throw new IOException("Error creating file: " + filename); + } + + //Create an XML representation of the branch profile + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + try { + docBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IOException("Error creating parser to produce XML document."); + } + Document doc = docBuilder.newDocument(); + + Element root = doc.createElement("branch-profile"); + root.setAttribute("application", DBT_Options.executableFile); + doc.appendChild(root); + + Element branchesElement = doc.createElement("branches"); + root.appendChild(branchesElement); + + for (int pc : branchSitesAndDestinations.keySet()) { + Element branchSiteElement = doc.createElement("origin"); + branchesElement.appendChild(branchSiteElement); + branchSiteElement.setAttribute("address", Integer.toString(pc)); + + for (int target : getKnownBranchTargets(pc)) { + Element branchTargetElement = doc.createElement("target"); + branchSiteElement.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(target)); + } + } + + //Output the resulting XML document + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} Modified: src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java =================================================================== --- src/org/binarytranslator/generic/branch/CallAndReturnAddress.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-07-06 10:39:15 UTC (rev 147) @@ -6,7 +6,7 @@ * * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 */ -package org.binarytranslator.generic.branch; +package org.binarytranslator.generic.branchprofile; /** * Object for recording a call site and its corresponding return address Deleted: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java =================================================================== --- src/org/binarytranslator/generic/branch/ProcedureInformation.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-06 10:39:15 UTC (rev 147) @@ -1,97 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.branch; - -import java.util.HashSet; -import java.util.Comparator; - -/** - * Objects capturing information about what looks like a method - */ -class ProcedureInformation { - /** - * Entry point to the procedure - */ - private int entry; - - /** - * Set of locations that call the procedure and the corressponding return - * address - */ - private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses; - - /** - * Set of locations within the procedure that return - */ - private HashSet<Integer> returnSites; - - /** - * Comparator for procedure information - */ - @SuppressWarnings("unused") - private static final class ProcedureInformationComparator implements - Comparator { - /** - * Compare two procedure information objects - */ - public int compare(Object o1, Object o2) { - return ((ProcedureInformation) o1).entry - - ((ProcedureInformation) o2).entry; - } - } - - /** - * Constructor - * - * @param entry - * starting address of the procedure - * @param callSite - * the address calling the procedure - * @param returnAddress - * the corresponding return address - */ - ProcedureInformation(int entry, int callSite, int returnAddress) { - this.entry = entry; - callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>(); - callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite, - returnAddress)); - } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerCall(int pc, int ret) { - CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret); - if (!callSitesAndReturnAddresses.contains(call_tuple)) { - callSitesAndReturnAddresses.add(call_tuple); - } - } - - /** - * Register a return (branch to link register) instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerReturn(int pc, int ret) { - if (returnSites == null) { - returnSites = new HashSet<Integer>(); - } - returnSites.add(new Integer(pc)); - // TODO: capture that the instruction prior to ret is a call - // site to this procedure - } -} Copied: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java (from rev 136, src/org/binarytranslator/generic/branch/ProcedureInformation.java) =================================================================== --- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java (rev 0) +++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-06 10:39:15 UTC (rev 147) @@ -0,0 +1,196 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.branchprofile; + +import java.util.HashSet; +import java.util.Comparator; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Objects capturing information about what looks like a method + */ +class ProcedureInformation { + /** + * Entry point to the procedure + */ + private final int entry; + + /** + * Set of locations that call the procedure and the corressponding return + * address + */ + private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses; + + /** + * Set of locations within the procedure that return + */ + private HashSet<Integer> returnSites; + + /** + * Comparator for procedure information + */ + @SuppressWarnings("unused") + private static final class ProcedureInformationComparator implements + Comparator { + /** + * Compare two procedure information objects + */ + public int compare(Object o1, Object o2) { + return ((ProcedureInformation) o1).entry + - ((ProcedureInformation) o2).entry; + } + } + + private ProcedureInformation(int entry) { + this.entry = entry; + } + + /** + * Constructor + * + * @param entry + * starting address of the procedure + * @param callSite + * the address calling the procedure + * @param returnAddress + * the corresponding return address + */ + ProcedureInformation(int entry, int callSite, int returnAddress) { + this.entry = entry; + callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>(); + callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite, + returnAddress)); + } + + /** + * Register a call (branch and link) instruction + * + * @param pc + * the address of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerCall(int pc, int ret) { + CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret); + if (!callSitesAndReturnAddresses.contains(call_tuple)) { + callSitesAndReturnAddresses.add(call_tuple); + } + } + + /** + * Register a return (branch to link register) instruction + * + * @param pc + * the address of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerReturn(int pc, int ret) { + if (returnSites == null) { + returnSites = new HashSet<Integer>(); + } + returnSites.add(new Integer(pc)); + } + + /** + * Serializes this object to an XML document. + * + * @param doc + * The XML document that the object shall be serialized to. + * @param parentNode + * The node within <code>doc</code> that the object shall be serialized to. + */ + public void toXML(Document doc, Element parentNode) { + Element procedure = parentNode; + procedure.setAttribute("entry", Integer.toString(entry)); + + Element callSites = doc.createElement("callsites"); + for (CallAndReturnAddress caller : callSitesAndReturnAddresses) { + Element callerNode = doc.createElement("call"); + callerNode.setAttribute("from", Integer.toString(caller.getCallSite())); + callerNode.setAttribute("return", Integer.toString(caller.getReturnAddress())); + callSites.appendChild(callerNode); + } + procedure.appendChild(callSites); + + Element returnSites = doc.createElement("returnsites"); + for (Integer returnSite : this.returnSites) { + Element returnSiteNode = doc.createElement("return"); + returnSiteNode.setAttribute("at", returnSite.toString()); + returnSites.appendChild(returnSiteNode); + } + procedure.appendChild(returnSites); + } + + /** + * Loads a {@link ProcedureInformation} object from an XML element, given that the object + * was previously persisted by {@link #toXML(Document, Element)}. + * @param node + * The XML element that had been provided to {@link #toXML(Document, Element)}. + */ + public static ProcedureInformation fromXML(Element node) { + + ProcedureInformation pi = new ProcedureInformation(Integer.parseInt(node.getAttribute("entry"))); + + for (int i = 0; i < node.getChildNodes().getLength(); i++) { + Node childNode = node.getChildNodes().item(i); + + //skip non-element nodes + if (childNode.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (childNode.getNodeName().equals("callsites")) { + //parse call sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("call")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int callFrom = Integer.parseInt(((Element)callsite).getAttribute("from")); + int callReturn = Integer.parseInt(((Element)callsite).getAttribute("return")); + + pi.callSitesAndReturnAddresses.add(new CallAndReturnAddress(callFrom, callReturn)); + } + } + else if (childNode.getNodeName().equals("returnsites")) { + //parse return sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("return")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int returnAt = Integer.parseInt(((Element)callsite).getAttribute("at")); + pi.returnSites.add(returnAt); + } + } + else { + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + } + } + + + + + + return pi; + } +} Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-06 10:39:15 UTC (rev 147) @@ -16,7 +16,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.Laziness.Key; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; Modified: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-06 10:39:15 UTC (rev 147) @@ -8,7 +8,7 @@ public enum Type { Translator, Interpreter, - PredecodingThreadedInterpreter, + PredecodingInterpreter, GDB } Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java =================================================================== --- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-06 10:39:15 UTC (rev 147) @@ -3,15 +3,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; public final class PredecodingThreadedInterpreter extends ExecutionController { - private HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); - private Interpreter interpreter; + private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); + private final Interpreter interpreter; private List<Interpreter.Instruction> getTrace(int pc) { List<Interpreter.Instruction> cachedTrace = traceCache.get(pc); @@ -58,11 +57,11 @@ public PredecodingThreadedInterpreter(ProcessSpace ps) { super(ps); + interpreter = ps.createInstructionInterpreter(); } @Override public void run() { - interpreter = ps.createInstructionInterpreter(); int pc = ps.getCurrentInstructionAddress(); while (!ps.finished) { Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-06 10:39:15 UTC (rev 147) @@ -14,8 +14,8 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; -import org.binarytranslator.generic.branch.BranchLogic; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.CodeCache; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.execution.GdbController.GdbTarget; @@ -33,7 +33,7 @@ public abstract class ProcessSpace { /** A record of branches to guide translation */ - public final BranchLogic branchInfo; + public final BranchProfile branchInfo; /** Has a system call been called to terminate the process? */ public boolean finished = false; @@ -123,7 +123,7 @@ * Constructor */ protected ProcessSpace() { - branchInfo = new BranchLogic(); + branchInfo = new BranchProfile(); codeCache = new CodeCache(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-07 00:27:11
|
Revision: 148 http://svn.sourceforge.net/pearcolator/?rev=148&view=rev Author: michael_baer Date: 2007-07-06 17:27:13 -0700 (Fri, 06 Jul 2007) Log Message: ----------- Minor fixes (unused imports etc.) Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-07 00:27:13 UTC (rev 148) @@ -13,7 +13,6 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.InstructionDecoder; -import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; Modified: src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-07-07 00:27:13 UTC (rev 148) @@ -12,7 +12,6 @@ import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; -import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls.SystemCall; /** * Linux system call handling class Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-07 00:27:13 UTC (rev 148) @@ -1141,6 +1141,8 @@ * a hint to allow for reuse of temps across instructions */ public OPT_RegisterOperand getTempInt(int num) { + if (DBT.VerifyAssertions) DBT._assert(num < 10); + if (intTemps == null) { intTemps = new OPT_Register[10]; } @@ -1164,10 +1166,14 @@ * a hint to allow for reuse of temps across instructions */ public OPT_RegisterOperand getTempLong(int num) { + if (DBT.VerifyAssertions) DBT._assert(num < 10); + if (longTemps == null) { longTemps = new OPT_Register[10]; } + OPT_Register result = longTemps[num]; + if (result == null) { OPT_RegisterOperand regOp = gc.temps.makeTempLong(); longTemps[num] = regOp.register; @@ -1211,7 +1217,7 @@ */ public OPT_RegisterOperand getTempFloat(int num) { if (DBT.VerifyAssertions) - DBT._assert((num == 0) || (num == 1)); + DBT._assert(num == 0 || num == 1); if (floatTemps == null) { floatTemps = new OPT_Register[2]; } @@ -1237,6 +1243,7 @@ public OPT_RegisterOperand getTempDouble(int num) { if (DBT.VerifyAssertions) DBT._assert(num == 0); + OPT_Register result = doubleTemp; if (result == null) { OPT_RegisterOperand regOp = gc.temps.makeTempDouble(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-09 10:36:57
|
Revision: 149 http://svn.sourceforge.net/pearcolator/?rev=149&view=rev Author: michael_baer Date: 2007-07-09 03:36:57 -0700 (Mon, 09 Jul 2007) Log Message: ----------- Refactorings in org.binarytranslator.generic.decoder: - Renamed classes - Cleaned up interfaces Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java src/org/binarytranslator/generic/decoder/CodeTranslator.java Removed Paths: ------------- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java src/org/binarytranslator/generic/decoder/InstructionDecoder.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -6,7 +6,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; @@ -17,7 +17,7 @@ import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; -public class ARM2IR extends AbstractCodeTranslator implements OPT_HIRGenerator { +public class ARM2IR extends CodeTranslator implements OPT_HIRGenerator { /** Mapping of ARM registers to HIR registers */ private OPT_Register regMap[] = new OPT_Register[16]; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-09 10:36:57 UTC (rev 149) @@ -21,6 +21,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; +import org.binarytranslator.generic.decoder.Disassembler; /** * This class transfers an ARM instruction into a human-readable assembly @@ -41,7 +42,7 @@ * The process space from which the instruction is read. * @return A disassembled ARM instruction. */ - public final static DisassembledInstruction disassemble(int address, + public final static Disassembler.Instruction disassemble(int address, ARM_ProcessSpace ps) { Instruction decodedInstruction; @@ -70,7 +71,7 @@ * The instruction that is to be decoded. * @return A human-readable version of the given instruction. */ - final static DisassembledInstruction disassemble( + final static Disassembler.Instruction disassemble( ARM_Instructions.Instruction instruction) { DisassemblingVisitor disassembler = new DisassemblingVisitor(); @@ -81,7 +82,7 @@ /** Represents a disassembled ARM instruction. */ private final static class ARM_DisassembledInstruction implements - DisassembledInstruction { + Disassembler.Instruction { /** A readable version of the diassembled instruction. */ private final String instruction; @@ -129,7 +130,7 @@ ARM_InstructionVisitor { /** This field receives the disassembled instruction. */ - private ARM_DisassembledInstruction result; + private Disassembler.Instruction result; private DisassemblingVisitor() { } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -7,13 +7,13 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; public abstract class ARM_ProcessSpace extends ProcessSpace { @@ -49,7 +49,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new ARM2IR(context, trace); } @@ -73,7 +73,7 @@ } @Override - public Interpreter createInstructionInterpreter() throws UnsupportedOperationException { + public Interpreter createInterpreter() throws UnsupportedOperationException { return new ARM_Interpreter(this); } Modified: src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-09 10:36:57 UTC (rev 149) @@ -111,7 +111,7 @@ int pc = startPC; ps.setCurrentInstructionAddress(startPC); - Interpreter interpreter = ps.createInstructionInterpreter(); + Interpreter interpreter = ps.createInterpreter(); ((ARM_ProcessSpace)ps).registers.set(ARM_Registers.LR, startPC); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,7 +14,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -42,7 +42,7 @@ * * @author Richard Matley, Ian Rogers */ -public final class PPC2IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public final class PPC2IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { // -oO Caches of references to process space entities Oo- Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,6 +14,7 @@ import org.binarytranslator.arch.ppc.decoder.PPC2IR; import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.memory.ByteAddressedByteSwapMemory; @@ -22,7 +23,6 @@ import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.jikesrvm.ppc.PPC_Disassembler; import org.vmmagic.pragma.Uninterruptible; @@ -140,7 +140,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new PPC2IR(context, trace); } Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -13,7 +13,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -25,7 +25,7 @@ import org.jikesrvm.compilers.opt.OPT_Constants; import org.jikesrvm.compilers.opt.ir.*; -public class X862IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public class X862IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { private static final VM_TypeReference psTref; Added: src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -0,0 +1,59 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.arch.x86.decoder; + +import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; +import org.binarytranslator.generic.fault.BadInstructionException; + +/** + * A decoder is a class capable of translating, interpretting or disassembling + * an instruction + */ +public abstract class X86_AbstractInstructionDecoder { + /** + * Translate a single instruction + * + * @param translationHelper + * the object containing the translation sequence + * @param ps + * the process space of the translation + * @param pc + * the address of the instruction to translate + * @return the address of the next instruction or -1 if this instruction has + * branched to the end of the trace + */ + public int translate(CodeTranslator translationHelper, ProcessSpace ps, + Object lazy, int pc) { + throw new Error("TODO"); + } + + /** + * Interpret a single instruction + * + * @param ps + * the process space of the interpretation, contains the fetched + * instruction and instruction address + * @return the next instruction interpreter + */ + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps) + throws BadInstructionException { + throw new Error("TODO"); + } + + /** + * Disassemble an instruction + * + * @param ps + */ + public String disassemble(ProcessSpace ps) { + // In general this isn't complete + throw new Error("Disassembly not yet complete"); + } +} Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,7 +12,6 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -22,7 +21,7 @@ /** * Decoder for X86 instructions */ -public class X86_InstructionDecoder extends InstructionDecoder { +public class X86_InstructionDecoder extends X86_AbstractInstructionDecoder { /* * Process defaults @@ -711,7 +710,7 @@ * instruction and instruction address * @return the next instruction interpreter */ - public InstructionDecoder interpret(ProcessSpace ps, int pc) + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps, int pc) throws BadInstructionException { X86_InstructionDecoder decoder = getDecoder(ps, pc); System.err.println("Attempt to interpret " + decoder.disassemble(ps, pc)); Modified: src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -10,7 +10,7 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; /** @@ -386,7 +386,7 @@ * Get the RM field as a decoded operand, the RM field encodes either a * register or memory location */ - X86_DecodedOperand getRM(AbstractCodeTranslator translationHelper, Laziness lazy, + X86_DecodedOperand getRM(CodeTranslator translationHelper, Laziness lazy, X86_SIB_Decoder sib, int displacement, int operandSize, int addressSize, int segment) { if (addressSize == 32) { Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,11 +12,11 @@ import java.util.Hashtable; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; @@ -149,7 +149,7 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new X862IR(context, trace); } Deleted: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-09 10:36:57 UTC (rev 149) @@ -1,1479 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.decoder; - -import java.util.Enumeration; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.Laziness.Key; -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.os.process.ProcessSpace; -import org.binarytranslator.vmInterface.DBT_Trace; -import org.jikesrvm.classloader.VM_Atom; -import org.jikesrvm.classloader.VM_BytecodeConstants; -import org.jikesrvm.classloader.VM_Class; -import org.jikesrvm.classloader.VM_MemberReference; -import org.jikesrvm.classloader.VM_Method; -import org.jikesrvm.classloader.VM_MethodReference; -import org.jikesrvm.classloader.VM_TypeReference; -import org.jikesrvm.compilers.opt.OPT_Constants; -import org.jikesrvm.compilers.opt.ir.Athrow; -import org.jikesrvm.compilers.opt.ir.BBend; -import org.jikesrvm.compilers.opt.ir.Call; -import org.jikesrvm.compilers.opt.ir.Goto; -import org.jikesrvm.compilers.opt.ir.IfCmp; -import org.jikesrvm.compilers.opt.ir.IfCmp2; -import org.jikesrvm.compilers.opt.ir.LookupSwitch; -import org.jikesrvm.compilers.opt.ir.Move; -import org.jikesrvm.compilers.opt.ir.New; -import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; -import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; -import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_Instruction; -import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_Operator; -import org.jikesrvm.compilers.opt.ir.OPT_Operators; -import org.jikesrvm.compilers.opt.ir.OPT_Register; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; - -/** - * A collection of common tools used by decoders. The public entry point for the - * translators is generateHIR(OPT_GenerationContext gc). - * - * <dl> - * <dt>Description of the translation algorithm</dt> - * <dd> - * <ol> - * <li>The translation is set up so that the start and end blocks are created. - * The start block branches to a prefill block that loads all the register - * values</li> - * <li>Translation starts from the PC value given in the DBT_Trace.</li> - * <li>Translation translates subject instructions to HIR using the - * translateInstruction method. This and the derived decoder object contain the - * utilities required to aid an instruction translation.</li> - * <li>The trace ends when the branch prediction deems it necessary. The - * closing basic blocks are generated and things are wrapped up.</li> - * </ol> - * </dd> - * </dl> - */ -public abstract class AbstractCodeTranslator implements OPT_Constants, - OPT_Operators { - - /** The trace that we're currently translating code for. */ - protected final DBT_Trace trace; - - /** VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace */ - private static final VM_TypeReference psTref; - - /** Method ProcessSpace.doSysCall */ - public static final VM_Method sysCallMethod; - - /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ - public static final VM_Class badInstrKlass; - - /** Method BadInstructionException.<init> */ - public static final VM_Method badInstrKlassInitMethod; - - /** Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> */ - public static final VM_Method recordUncaughtBranchMethod; - - static { - psTref = VM_TypeReference.findOrCreate(ProcessSpace.class); - VM_MethodReference sysCallMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom.findOrCreateAsciiAtom("doSysCall"), - VM_Atom.findOrCreateAsciiAtom("()V")); - sysCallMethod = sysCallMethRef.resolveInvokeSpecial(); - - badInstrKlass = VM_TypeReference.findOrCreate(BadInstructionException.class).resolve().asClass(); - - VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate( - badInstrKlass.getTypeRef(), - VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom - .findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); - badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); - - VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom - .findOrCreateAsciiAtom("recordUncaughtBranch"), VM_Atom - .findOrCreateAsciiAtom("(IIII)V")); - recordUncaughtBranchMethod = recordUncaughtBranchMethRef - .resolveInvokeSpecial(); - } - - /** Number of translated instructions */ - private int numberOfInstructions; - - /** The process space object used by the running binary. */ - public final ProcessSpace ps; - - /** The VM method's generation context. */ - protected OPT_GenerationContext gc; - - /** The OPT_BasicBlock in which instructions are currently being inserted */ - protected OPT_BasicBlock currentBlock; - - /** The pc value corresponding to the instruction currently being translated */ - protected int currentPC; - - /** The pc value of the first instruction in the trace */ - protected int startingPC; - - /** The OPT_BasicBlock which will contain the next translated instruction */ - protected OPT_BasicBlock nextBlock; - - /** - * The basic block is used by finish trace to hold all the code that must be - * executed before returning to the main run loop - */ - protected OPT_BasicBlock finishBlock; - - /** - * This block gets instructions to pre-fill registers inserted into it. - */ - protected OPT_BasicBlock preFillBlock; - - /** - * This variable is being set by a call to {@link #printTraceAfterCompletion()} and notifies - * the system that the current trace shall be printed, after it has been completed. */ - private boolean requestPrintTrace; - - /** Map to locate HIR basic blocks to re-use translation within a trace */ - protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - - /** This class stores information about a jump instruction within the current trace, whose - * target has not yet been resolved. */ - private final static class UnresolvedJumpInstruction { - - /** A reference to the jump instruction within the code. This is either a GOTO or SWITCH instruction. */ - public final OPT_Instruction instruction; - - /** The lazy state at the jump location. */ - public final Laziness lazyStateAtJump; - - /** Stores the target of the jump instruction or -1, if this value is unknown. */ - public final int targetPC; - - /** Stores the address, at which the jump occurs*/ - public final int pc; - - /** Identifies the type of branch. */ - public final BranchType type; - - public UnresolvedJumpInstruction(OPT_Instruction instruction, - Laziness lazyStateAtJump, int pc, int targetPC, BranchType type) { - this.instruction = instruction; - this.lazyStateAtJump = lazyStateAtJump; - this.pc = pc; - this.type = type; - this.targetPC = targetPC; - } - } - - /** - * List of unresolved direct branches. The destinations of direct branches are - * already known at translation time. */ - private final List<UnresolvedJumpInstruction> unresolvedDirectBranches; - - /** - * List of unresolved dynamic branches. Dynamics branches have a destination - * address that is only determined at runtime. */ - private final List<UnresolvedJumpInstruction> unresolvedDynamicBranches; - - /** - * Constructor - * - * @param context - * The JRVM generation context for this trace. - */ - protected AbstractCodeTranslator(OPT_GenerationContext context, - DBT_Trace trace) { - - // Store the trace that we're invoked from - this.trace = trace; - - // Make copies of popular variables - gc = context; - ps = ((DBT_Trace) (gc.method)).ps; - currentPC = ((DBT_Trace) (gc.method)).pc; - startingPC = currentPC; - - // Number of translated instructions - numberOfInstructions = 0; - - // Create map of (PC & laziness) -> OPT_BasicBlock - blockMap = new HashMap<Key, OPT_BasicBlock>(); - - // Create preFillBlock, currentBlock and finishBlock - gc.prologue.insertOut(gc.epilogue); - preFillBlock = createBlockAfter(gc.prologue); - currentBlock = createBlockAfter(preFillBlock); - finishBlock = createBlockAfterCurrent(); - - // Fix up stores - unresolvedDirectBranches = new LinkedList<UnresolvedJumpInstruction>(); - unresolvedDynamicBranches = new LinkedList<UnresolvedJumpInstruction>(); - } - - /** Returns the number of previously translated instructions within this trace. */ - public int getNumInstructions() { - return numberOfInstructions; - } - - /** - * Deriving classes may call this method if they want to print the current trace after all - * dependencies (unknown branch targets etc.) have been resolved. This function is useful for - * debug purposes. - */ - protected void printTraceAfterCompletion() { - requestPrintTrace = true; - } - - /** This is the main loop, which generates the HIR. */ - public void generateHIR() { - // Load all the register values to be used in a trace - preFillAllRegisters(); - - // Translate from the current program counter - translateSubTrace(createInitialLaziness(), currentPC); - - // Translating the subtrace finished so resolve any unresolved branches - - while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) { - // Resolve all open direct branches first - resolveAllDirectBranches(); - - // Resolve unresolved dynamic jumps - resolveAllDynamicBranches(); - } - - // Finish up the trace - finishTrace(); - - if (DBT_Options.eliminateRegisterFills) { - eliminateRegisterFills(getUnusedRegisters()); - } - - if (requestPrintTrace) { - requestPrintTrace = false; - printNextBlocks(preFillBlock, 50); - } - - // TODO: maximizeBasicBlocks() - } - - /** - * Translate a sequence of instructions upto an instruction that doesn't know - * its immediate/default successor. The currentBlock should be an empty basic - * block. - */ - private void translateSubTrace(Laziness lazy, int pc) { - currentPC = pc; - - if (shallTraceStop()) { - // Record mapping of this pc value and laziness to this block - registerMapping(pc, lazy, currentBlock); - // Create next block - nextBlock = createBlockAfterCurrent(); - // Finish block to return and exit - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - // Move currentBlock along - currentBlock = nextBlock; - } else { - do { - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - - // Record mapping of this pc value and laziness to this block - registerMapping(pc, lazy, currentBlock); - - // Create next block - nextBlock = createBlockAfterCurrent(); - - // Translare instruction and get address of next instruction - pc = translateInstruction(lazy, pc); - numberOfInstructions++; - - // Move currentBlock along - currentBlock = nextBlock; - currentPC = pc; - - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - - // Are we translating in single instruction mode - if (DBT_Options.singleInstrTranslation == true) { - if (pc != -1) { - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - } - - break; - } - - // Do we already have a translation for this next block? - OPT_BasicBlock possibleNextBlock = findMapping(pc, lazy); - if (possibleNextBlock != null) { - // Yes, branch to that and stop translating - appendInstruction(Goto.create(GOTO, possibleNextBlock - .makeJumpTarget())); - OPT_BasicBlock gotoBlock = currentBlock; - currentBlock = createBlockAfterCurrent(); - gotoBlock.deleteNormalOut(); - gotoBlock.insertOut(possibleNextBlock); - if (DBT.VerifyAssertions) - DBT._assert(gotoBlock.getNumberOfNormalOut() == 1); - break; - } - } while (pc != -1); - } - } - - /** - * Get the block which is currently having instructions inserted into it - * - * @return the current block - */ - public OPT_BasicBlock getCurrentBlock() { - return currentBlock; - } - - /** - * Get the block which will contain the translation of the next PPC - * instruction - * - * @return the next block - */ - public OPT_BasicBlock getNextBlock() { - return nextBlock; - } - - /** - * Set the block which is currently having instructions inserted into it - * - * @param newCurrentBlock - * the new current basic block - */ - public void setCurrentBlock(OPT_BasicBlock newCurrentBlock) { - currentBlock = newCurrentBlock; - } - - /** - * Set the block which will contain the translation of the next PPC - * instruction - * - * @param newCurrentBlock - * the new next basic block - */ - public void setNextBlock(OPT_BasicBlock newNextBlock) { - nextBlock = newNextBlock; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into the CFG and code ordering - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrent() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - /* - * if (DBT.VerifyAssertions) DBT._assert(currentBlock.isOut(nxtBlock)); - */ - - if (currentBlock.isOut(nxtBlock)) { - currentBlock.deleteOut(nxtBlock); - currentBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); - } else { - currentBlock.insertOut(newBlock); - } - - if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, - currentBlock)); - } - - return newBlock; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into code ordering but not the CFG - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrentNotInCFG() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", - newBlock, currentBlock)); - } - return newBlock; - } - - /** - * Create a basic block immediately after the given block and link its edges - * into the CFG and code ordering - * - * @param afterBlock - * The block after which the new block is to be created. - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { - OPT_BasicBlock nxtBlock = afterBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(afterBlock, nxtBlock); - gc.cfg.linkInCodeOrder(afterBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT.VerifyAssertions) - DBT._assert(afterBlock.isOut(nxtBlock)); - afterBlock.deleteOut(nxtBlock); - afterBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, - afterBlock)); - } - - return newBlock; - } - - /** - * Append a HIR instruction to the current basic block - * - * @param i - * The instruciton that is to be appended to the current bloc. - */ - public void appendInstruction(OPT_Instruction i) { - if (i.bcIndex == UNKNOWN_BCI) { - i.position = gc.inlineSequence; - // we only have 16bits to distinguish instructions (the bcIndex - // is effective 16bit when stored in the machine code map), - // Intel can't distinguish branches within 16bytes, so neither - // can we, the top bit is saved for distinguished addresses we - // need to know to dynamically link things - i.bcIndex = ((currentPC - startingPC) >> 4) & 0x7FFF; - } - currentBlock.appendInstruction(i); - } - - /** - * Generate a branch profile operand for the current instruction - * - * @param likely - * Does this branch have a likely hint? - */ - public OPT_BranchProfileOperand getConditionalBranchProfileOperand( - boolean likely) { - return gc.getConditionalBranchProfileOperand( - ((currentPC - startingPC) >> 4) & 0x7FFF, likely); - } - - /** - * We're finished translating this trace so .. 1) put all the registers back - * into the process space 2) return the new PC value - */ - protected void finishTrace() { - // finishBlock is already linked into the cfg, we just need to - // make sure we are adding to it. - currentBlock = finishBlock; - spillAllRegisters(); - } - - /** - * Get the generation context. - */ - public OPT_GenerationContext getGenerationContext() { - return gc; - } - - /** - * Register a mapping between a pc and lazy and a hir block - * - * @param pc - * The program counter whose translation the basic bock represents. - * @param lazy - * The lazy state that is assumed for this basic block. - * @param hirBlock - * The block that is to be registered. - */ - protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { - blockMap.put(lazy.makeKey(pc), hirBlock); - } - - /** - * Find if there's already a translation for a given pc and laziness - * - * @param pc - * The program counter address at which the returned basic block - * shall start. - * @param lazy - * The lazy state assumed within the returned trace. - * @return An appropriate basic block or null if no translation exists. - */ - protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { - return blockMap.get(lazy.makeKey(pc)); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendBranch(int targetPC, Laziness targetLaziness) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Appends the conditional branch instruction <code>conditional</code> that jumps to the address - * <code>targetPc</code> to the current block. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendConditionalBranch(OPT_Instruction conditional, int targetPC, Laziness targetLaziness) { - - if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(conditional) || IfCmp2.conforms(conditional)); - appendStaticBranch(conditional, targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - * @param branchType - * The type of branch that best describes this jump. - */ - public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.CALL, retAddr); - } - - private void appendStaticBranch(OPT_Instruction branch, int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { - // Place a GOTO instruction at this point. However, this instruction - // serves more as a placeholder and might be mutated later on. - appendInstruction(branch); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); - unresolvedDirectBranches.add(unresolvedJump); - - if (branchType == BranchType.CALL) - ps.branchInfo.registerCall(currentPC, targetPC, retAddr); - else - if (branchType == BranchType.RETURN) - ps.branchInfo.registerReturn(currentPC, targetPC); - else - ps.branchInfo.registerBranch(currentPC, targetPC, branchType); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param retAddr - * The address, to which the function call will (most likely) return. - */ - public void appendCall(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, int retAddr) { - - appendDynamicBranch(targetAddress, lazyStateAtJump, BranchType.CALL, retAddr); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - */ - public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { - - if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); - - appendDynamicBranch(targetAddress, lazyStateAtJump, branchType, -1); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - * @param retAddr - * The address, to which the function call will (most likely) return or an arbitrary value, if - * branchType is not BranchType.CALL. - */ - private void appendDynamicBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType, int retAddr) { - - OPT_BasicBlock fallThrough = createBlockAfterCurrent(); - OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress.copyRO(), null, null, fallThrough.makeJumpTarget(), null, 0); - appendInstruction(switchInstr); - - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, -1, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress); - - } - - /** Resolve all unresolved direct branch instructions. */ - private void resolveAllDirectBranches() { - - while (unresolvedDirectBranches.size() > 0) { - - // Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(0); - int targetPc = unresolvedInstr.targetPC; - Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; - OPT_Instruction gotoInstr = unresolvedInstr.instruction; - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); - - if (DBT_Options.debugBranchResolution) { - report("Resolved goto in block " + gotoInstr.getBasicBlock() - + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); - } - - // Fix up instruction - setBranchTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().insertOut(targetBB); - } - } - - /** - * Sets the target of the branching instruction <code>branch</code> to <code>target</code>. - * @param branch - * A branching instruction. Either a Goto or - * @param target - * The jump target. - */ - private void setBranchTarget(OPT_Instruction branch, OPT_BranchOperand target) { - if (Goto.conforms(branch)) { - Goto.setTarget(branch, target); - } - else if (IfCmp.conforms(branch)) { - IfCmp.setTarget(branch, target); - } - else if (IfCmp2.conforms(branch)) { - IfCmp2.setTarget1(branch, target); - } - } - - /** - * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the - * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when - * the jump target is not part of the current trace anyway. - * - * This function may be overriden to fine-tune whether certain branches shall be inlined or not. - * - * @param targetPc - * The address that we're jumping to. - * @param jump - * Detailled information describing the jump. - * @return - * True to make the system inline the target of this branch, false otherwise. - */ - protected boolean inlineBranchInstruction(int targetPc, UnresolvedJumpInstruction jump) { - /* - * The target Block is not yet translated. We do not want to inline it - * into the current trace if a) DBT_Options.singleInstrTranslation is - * enabled b) The jump target has already been compiled as a separate method - * within the code cache c) The trace is already too long d) the branch is - * supposedly a CALL or RETURN - */ - return DBT_Options.singleInstrTranslation == false - && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop() - && jump.type != BranchType.CALL && jump.type != BranchType.RETURN; - } - - /** - * Resolves a branch target to an actual basic block. In case the jump target - * is not yet part of this trace, this method also takes a decision about - * whether the target shall be translated into the trace. - * - * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, - * this method will always end the current trace, just returning the address - * of the next instruction. - * - * @param targetPc - * The address of the target basic block that. - * @param jump - * The branch instruction that we are trying to resolve. - * @return A basic block that is equivalent to the program counter address - * <code>targetPc</code> in the original binary. - */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, UnresolvedJumpInstruction jump) { - // Resolve the address of the target block - OPT_BasicBlock targetBB = findMapping(targetPc, jump.lazyStateAtJump); - - // If the target is already part of this trace, then just use the - // precompiled target - if (targetBB != null) - return targetBB; - - if (inlineBranchInstruction(targetPc, jump)) { - - // Just exit the trace and continue at the target address in a new trace - if (currentBlock.getNumberOfRealInstructions() != 0) { - currentBlock = createBlockAfterCurrentNotInCFG(); - - if (DBT_Options.debugBranchResolution) - System.out.println("Resolving branch to next block."); - } - - targetBB = currentBlock; - appendTraceExit(jump.lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - registerMapping(targetPc, jump.lazyStateAtJump, targetBB); - } else { - // Otherwise we will translate the jump into the trace - translateSubTrace((Laziness) jump.lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, jump.lazyStateAtJump); - } - - if (DBT.VerifyAssertions) - DBT._assert(targetBB != null); - - return targetBB; - } - - /** - * Resolves all dynamic branches that have been added with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - */ - private void resolveAllDynamicBranches() { - - while (unresolvedDynamicBranches.size() > 0) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.remove(0); - Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - - resolveSingleDynamicJump(unresolvedSwitch, branchDests); - } - } - - /** - * Resolves a single dynamic jump that has previously been created with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - * - * @param lazy - * The lazy state of the jump that is to be resolved. - * @param lookupswitch - * Each dynamic jump is converted to a switch statement. This is the - * switch statement for the current jump. - * @param destinations - * A list of known destinations that this dynamic jumps branches to. - */ - private void resolveSingleDynamicJump( - UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) - throws Error { - - if (DBT.VerifyAssertions) - DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); - - OPT_Instruction lookupswitch = unresolvedJump.instruction; - OPT_BranchOperand default_target = LookupSwitch.getDefault(lookupswitch); - OPT_Operand value = LookupSwitch.getValue(lookupswitch); - - if (destinations != null && destinations.size() > 0) { - if ((destinations.size() > 1) - || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target - .getBasicBlock())) { - float branchProb = (1.0f - OPT_BranchProfileOperand.UNLIKELY) - / (float) destinations.size(); - LookupSwitch.mutate(lookupswitch, LOOKUPSWITCH, value, null, null, - default_target, OPT_BranchProfileOperand.unlikely(), destinations - .size() * 3); - int match_no = 0; - for (int dest_pc : destinations) { - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); - - LookupSwitch.setMatch(lookupswitch, match_no, - new OPT_IntConstantOperand(dest_pc)); - LookupSwitch.setTarget(lookupswitch, match_no, target - .makeJumpTarget()); - LookupSwitch.setBranchProfile(lookupswitch, match_no, - new OPT_BranchProfileOperand(branchProb)); - lookupswitch.getBasicBlock().insertOut(target); - match_no++; - } - } else { - int dest_pc = destinations.iterator().next(); - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); - - IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, - new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), - target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); - lookupswitch.getBasicBlock().insertOut(target); - } - } else { - //we don't yet know where this jump will go, so just do nothing, which will exit the trace - } - } - - /** - * Set the return value in the currentBlock, resolve its lazy state (so the - * state is no longer lazy) and then set it to branch to the finish block - * - * @param nextPc - * return value for translated code (the PC value of the next - * instruction to translate) - */ - public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - // Copy the value into the register specified by gc.resultReg. - appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand( - gc.resultReg, VM_TypeReference.Int), nextPc.copy())); - resolveLaziness(laziness); - appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); - currentBlock.deleteNormalOut(); - currentBlock.insertOut(finishBlock); - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - } - - /** - * Should the trace be stopped as soon as possible? This function can be used - * to steer how large a single trace may be. Return true if the target size - * for the trace is about to be or has been exceeded. - * - * @return true => try to stop the trace - */ - protected boolean shallTraceStop() { - if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { - return true; - } - - switch (gc.options.getOptLevel()) { - case 0: - return numberOfInstructions > DBT_Options.instrOpt0; - case 1: - return numberOfInstructions > DBT_Options.instrOpt1; - default: - return numberOfInstructions > DBT_Options.instrOpt2; - } - } - - /** - * Register a branch and link instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address returned to - * @param dest - * the destination of the branch instruction - */ - public void registerBranchAndLink(int pc, int ret, int dest) { - ps.branchInfo.registerCall(pc, ret, dest); - } - - /** - * Returns a vector of likely branch targets for the branch at address - * <code>pc</code>. - * - * @param pc - * The location at which the branch occurs. - * @return A set of likely destinations for that jump. - */ - private Set<Integer> getLikelyJumpTargets(int pc) { - return ps.branchInfo.getKnownBranchTargets(pc); - } - - /** - * Should a trace follow a branch and link instruction or should it terminate - * the trace? - * - * @param pc - * the address of the branch and link instruction - * @return whether the trace should continue - */ - public boolean traceContinuesAfterBranchAndLink(int pc) { - return shallTraceStop() == false; - } - - /** - * Load all the registers from the ProcessSpace into the pre-fill block - */ - private void preFillAllRegisters() { - OPT_BasicBlock temp = currentBlock; - currentBlock = preFillBlock; - fillAllRegisters(); - ps.memory.initTranslate(this); // Set up memory - currentBlock = temp; - } - - /** - * Eliminate unnecessary register spill and fill code - ie a register wasn't - * used so eliminate references to it - */ - protected void eliminateRegisterFills(OPT_Register unusedRegisters[]) { - if (unusedRegisters.length > 0) { - OPT_BasicBlock curBB = gc.prologue; - while (curBB != null) { - OPT_Instruction curInstr = curBB.firstInstruction(); - loop_over_instructions: while (BBend.conforms(curInstr) == false) { - for (Enumeration du = curInstr.getRootOperands(); du - .hasMoreElements();) { - OPT_Operand curOp = (OPT_Operand) du.nextElement(); - if (curOp.isRegister()) { - OPT_Register curReg = curOp.asRegister().register; - for (int i = 0; i < unusedRegisters.length; i++) { - if (unusedRegisters[i] == curReg) { - OPT_Instruction toRemove = curInstr; - curInstr = curInstr.nextInstructionInCodeOrder(); - toRemove.remove(); - continue loop_over_instructions; - } - } - } - } - curInstr = curInstr.nextInstructionInCodeOrder(); - } - curBB = curBB.nextBasicBlockInCodeOrder(); - } - } - } - - /** - * Appends a system call to the current basic block. - * - * @param lazy - * current translation laziness - * @param pc - * address of system call instruction - */ - public void appendSystemCall(Laziness lazy) { - // We need to make sure that all registers contain their latest values, - // before performing the actual system call. - resolveLaziness(lazy); - spillAllRegisters(); - - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); - - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(sysCallMethod - .getMemberRef().asMethodReference(), sysCallMethod); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, - new OPT_AddressConstantOperand(sysCallMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.DO_SYSCALL; - appendInstruction(s); - - // Fill all registers again following system call - fillAllRegisters(); - } - - /** - * Plant a throw of a bad instruction exception - * - * @param lazy - * current translation laziness - * @param pc - * the program counter of the bad instruction - */ - public void appendThrowBadInstruction(Laziness lazy, int pc) { - // We need to make sure that all registers contain their latest values, - // before - // throwing the bad instruction exception. - resolveLaziness(lazy); - spillAllRegisters(); - - OPT_Operator newOperator; - OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); - VM_TypeReference eTref = badInstrKlass.getTypeRef(); - - if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { - newOperator = NEW; - } else { - newOperator = NEW_UNRESOLVED; - } - - OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); - OPT_Instruction n = New.create(newOperator, eRef, typeOperand); - n.position = gc.inlineSequence; - n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - appendInstruction(n); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); - OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( - badInstrKlassInitMethod.getMemberRef().asMethodReference(), - badInstrKlassInitMethod); - Call.setParam(c, 0, eRef.copy()); // 'this' pointer in - // BadInstructionException.init - Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); - Call.setParam(c, 2, psRef); - Call.setGuard(c, new OPT_TrueGuardOperand()); - Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod - .getOffset())); - c.position = gc.inlineSequence; - c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; - - appendInstruction(c); - - OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); - t.position = gc.inlineSequence; - t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; - - appendInstruction(t); - - appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); - } - - /** - * Plant a record uncaught branch call. NB register state won't get resolved - * for call - * - * @param pc - * the address of the branch instruction - * @param destination - * the register operand holding the destination - * @param branchType - * The type of the uncaught branch - * @param retAddr - * An optional return address, in case the branch is a call. Otherwise, this value is ignored. - */ - private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType, int retAddr) { - // Is it sensible to record this information? - if ((gc.options.getOptLevel() > 0) - && (DBT_Options.plantUncaughtBranchWatcher)) { - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 5); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( - recordUncaughtBranchMethod.getMemberRef().asMethodReference(), - recordUncaughtBranchMethod); - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer - Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch - // instruction - Call.setParam(s, 2, destination.copy()); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type - Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address - // value - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand( - recordUncaughtBranchMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.RECORD_BRANCH; - appendInstruction(s); - } - } - - /** Temporary int variables */ - private OPT_Register intTemps[]; - - /** - * Get/create a temporary int - * - * @param num - * a hint to allow for reuse of temps across instructions - */ - public OPT_RegisterOperand getTempInt(int num) { - if (DBT.VerifyAssertions) DBT._assert(num < 10); - - if (intTemps == null) { - intTemps = new OPT_Register[10]; - } - OPT_Register result = intTemps[num];... [truncated message content] |
From: <mic...@us...> - 2007-08-02 13:59:59
|
Revision: 154 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=154&view=rev Author: michael_baer Date: 2007-08-02 06:59:57 -0700 (Thu, 02 Aug 2007) Log Message: ----------- - Corrected bug in staged emulation controller - added javadoc Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java src/org/binarytranslator/generic/execution/StagedEmulationController.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-08-02 12:22:44 UTC (rev 153) +++ src/org/binarytranslator/DBT_Options.java 2007-08-02 13:59:57 UTC (rev 154) @@ -90,6 +90,9 @@ /** GDB stub port */ public static int gdbStubPort = 1234; + /** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */ + public static int minTraceValue = 20; + /** Print debug information during the translation of instructions. */ public static boolean debugTranslation = true; @@ -153,49 +156,52 @@ } /** Parses a single argument into the options class. */ - private static void parseSingleArgument(String arg, String value) { + private static void parseSingleArgument(String key, String value) { - if (!arg.startsWith("-X:dbt:")) { + if (!key.startsWith("-X:dbt:")) { throw new Error("Invalid argument. Argument prefix '-X:dbt:' expected."); } - arg = arg.substring(7); + key = key.substring(7); - if (arg.equalsIgnoreCase("debugInstr")) { + if (key.equalsIgnoreCase("debugInstr")) { debugInstr = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("debugRuntime")) { + } else if (key.equalsIgnoreCase("debugRuntime")) { debugRuntime = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("debugBranchResolution")) { + } else if (key.equalsIgnoreCase("debugBranchResolution")) { debugBranchResolution = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("debugMemory")) { + } else if (key.equalsIgnoreCase("debugMemory")) { debugMemory = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("debugSyscall")) { + } else if (key.equalsIgnoreCase("debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("debugSyscallMore")) { + } else if (key.equalsIgnoreCase("debugSyscallMore")) { debugSyscallMore = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("instrOpt0")) { + } else if (key.equalsIgnoreCase("instrOpt0")) { instrOpt0 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("instrOpt1")) { + } else if (key.equalsIgnoreCase("instrOpt1")) { instrOpt1 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("instrOpt2")) { + } else if (key.equalsIgnoreCase("instrOpt2")) { instrOpt2 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("singleInstrTranslation")) { + } else if (key.equalsIgnoreCase("singleInstrTranslation")) { singleInstrTranslation = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("resolveDirectBranchesFirst")) { + } else if (key.equalsIgnoreCase("resolveDirectBranchesFirst")) { resolveDirectBranchesFirst = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("gdbStub")) { + } else if (key.equalsIgnoreCase("gdbStub")) { gdbStub = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("gdbStubPort")) { + } else if (key.equalsIgnoreCase("gdbStubPort")) { gdbStubPort = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("controller")) { + } else if (key.equalsIgnoreCase("controller")) { executionController = ExecutionController.Type.valueOf(value); - } else if (arg.equalsIgnoreCase("loadProfile")) { - loadProfileFromFile = arg; - } else if (arg.equalsIgnoreCase("saveProfile")) { - saveProfileToFile = arg; + } else if (key.equalsIgnoreCase("loadProfile")) { + loadProfileFromFile = value; + } else if (key.equalsIgnoreCase("saveProfile")) { + saveProfileToFile = value; + } else if (key.equalsIgnoreCase("minTraceValue")) { + minTraceValue = Integer.parseInt(value); } + else { - throw new Error("Unknown DBT option: " + arg); + throw new Error("Unknown DBT option: " + key); } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-08-02 12:22:44 UTC (rev 153) +++ src/org/binarytranslator/Main.java 2007-08-02 13:59:57 UTC (rev 154) @@ -105,7 +105,7 @@ //on SUN's VM, only the interpreter has been tested if (DBT_Options.buildForSunVM) { - DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter; + DBT_Options.executionController = ExecutionController.Type.StagedEmulation; } //load a previously saved branch profile from file, if the user requested it Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 12:22:44 UTC (rev 153) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 13:59:57 UTC (rev 154) @@ -1,9 +1,12 @@ package org.binarytranslator.generic.execution; -import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; +/** + * Implements straight-forward interpretation using the {@link Interpreter} + * and {@link Interpreter.Instruction} interfaces. + */ public class InterpreterController extends ExecutionController { public InterpreterController(ProcessSpace ps) { Modified: src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 12:22:44 UTC (rev 153) +++ src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 13:59:57 UTC (rev 154) @@ -3,6 +3,12 @@ import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; +/** + * Implements straight-forward interpretation using the {@link Interpreter} + * and {@link Interpreter.Instruction} interfaces. + * + * Additionally, this controller performs profiling during the interpretation. + */ public class ProfilingInterpreterController extends ExecutionController { public ProfilingInterpreterController(ProcessSpace ps) { Modified: src/org/binarytranslator/generic/execution/StagedEmulationController.java =================================================================== --- src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 12:22:44 UTC (rev 153) +++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 13:59:57 UTC (rev 154) @@ -13,24 +13,46 @@ import org.binarytranslator.vmInterface.DynamicCodeRunner; import org.jikesrvm.ArchitectureSpecific.VM_CodeArray; +/** + * This controller implements staged emulation, i.e. switching between interpretation + * and translation dynamically. + * + */ public class StagedEmulationController extends ExecutionController { - private final class Trace { - public final List<Interpreter.Instruction> instructions; + /** Represents a dynamic basic block of instructions. */ + private final class DynamicBasicBlock { + /** The instructions within this dynamic basic block. */ + public List<Interpreter.Instruction> instructions; + + /** A value describing how "hot" the basic block is, i.e. how often it has been executed.*/ public int value; + + /** A handle to the compiled version of this dynamic basic block or null, if there is none. */ public DBT_Trace compiledTrace; - public Trace(List<Interpreter.Instruction> instructions) { + public DynamicBasicBlock(List<Interpreter.Instruction> instructions) { this.instructions = instructions; value = 0; } } - private final HashMap<Integer, Trace> traceCache = new HashMap<Integer, Trace>(); + /** Maps a dynamic basic block to the address of the first instruction within that block. */ + private final HashMap<Integer, DynamicBasicBlock> traceCache = new HashMap<Integer, DynamicBasicBlock>(); + + /** The interpreter that is used to perform the actual execution of single instructions. */ private final Interpreter interpreter; - private Trace getTrace(int pc) { - Trace cachedTrace = traceCache.get(pc); + /** + * Returns the dynamic basic block starting at address <code>pc</code>. + * + * @param pc + * The starting address of a dynamic basic block. + * @return + * An object representation of the dynamic basic block. + */ + private DynamicBasicBlock getBlock(int pc) { + DynamicBasicBlock cachedTrace = traceCache.get(pc); if (cachedTrace != null) return cachedTrace; @@ -46,7 +68,7 @@ //is the successor to this instruction known? if (pc == -1) { //No, so stop and create a trace from the decoded instructions - Trace newTrace = new Trace(instructions); + DynamicBasicBlock newTrace = new DynamicBasicBlock(instructions); if (instructions.size() > 3) { //add this trace to the trace cache, if it contains enough instructions @@ -58,17 +80,34 @@ } } - private void compileTrace(Trace trace, int pc) { + /** + * Compiles a dynamic basic block into a trace. + * + * @param trace + * The dynamic basic block to compile. + * @param pc + * The address of the first instruction within the dynamic basic block. + */ + private void compileBlock(DynamicBasicBlock trace, int pc) { if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace == null); trace.compiledTrace = new DBT_Trace(ps, pc); trace.compiledTrace.compile(); + trace.instructions = null; } - private void executeTrace(Trace trace, int pc) { + /** + * Executes the instructions within a dynamic basic block. + * + * @param trace + * The dynamic basic block whose instructions shall be executed. + * @param pc + * The address of the first instruction within that dynamic basic block. + */ + private void executeBlock(DynamicBasicBlock trace, int pc) { //check if the trace is being executed very frequently... - if (trace.value > 20) { + if (trace.value > DBT_Options.minTraceValue) { if (DBT_Options.debugTranslation) System.out.println("Switching to interpretation at address 0x" + Integer.toHexString(pc)); @@ -76,13 +115,18 @@ //yes, so we should rather try to execute a translated version if (trace.compiledTrace == null) { //compile the trace, if necessary - compileTrace(trace, pc); + compileBlock(trace, pc); if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace != null); } //execute the trace VM_CodeArray code = trace.compiledTrace.getCurrentCompiledMethod().getEntryCodeArray(); ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps)); + + if (DBT_Options.debugTranslation) + System.out.println("Returning from interpretation at 0x" + Integer.toHexString(ps.getCurrentInstructionAddress())); + + return; } else { trace.value += trace.instructions.size(); @@ -102,6 +146,7 @@ } } + /** Default constructor */ public StagedEmulationController(ProcessSpace ps) { super(ps); interpreter = ps.createInterpreter(); @@ -113,8 +158,8 @@ while (!ps.finished) { - Trace trace = getTrace(pc); - executeTrace(trace, pc); + DynamicBasicBlock trace = getBlock(pc); + executeBlock(trace, pc); pc = ps.getCurrentInstructionAddress(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-08-06 15:25:10
|
Revision: 158 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=158&view=rev Author: michael_baer Date: 2007-08-06 08:25:12 -0700 (Mon, 06 Aug 2007) Log Message: ----------- - Made optimizations by profiling optional Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/generic/decoder/CodeTranslator.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-08-06 15:23:44 UTC (rev 157) +++ src/org/binarytranslator/DBT_Options.java 2007-08-06 15:25:12 UTC (rev 158) @@ -93,6 +93,9 @@ /** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */ public static int minTraceValue = 20; + /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information.. */ + public static boolean optimizeTranslationByProfiling = false; + /** Print debug information during the translation of instructions. */ public static boolean debugTranslation = true; @@ -198,8 +201,9 @@ saveProfileToFile = value; } else if (key.equalsIgnoreCase("minTraceValue")) { minTraceValue = Integer.parseInt(value); + } else if (key.equalsIgnoreCase("optimizeTranslation")) { + optimizeTranslationByProfiling = Boolean.parseBoolean(value); } - else { throw new Error("Unknown DBT option: " + key); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-06 15:23:44 UTC (rev 157) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-06 15:25:12 UTC (rev 158) @@ -756,23 +756,31 @@ arm2ir.getCurrentBlock().insertOut(condBlock); //Query the branch profile to get the probability that this instruction is going to get executed - float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4)); OPT_BranchProfileOperand profileOperand; - if (skipProbability == -1 || skipProbability == 0.5f) { - profileOperand = new OPT_BranchProfileOperand(); + if (DBT_Options.optimizeTranslationByProfiling) { + float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4)); + + if (skipProbability == -1 || skipProbability == 0.5f) { + profileOperand = new OPT_BranchProfileOperand(); + } + else if (skipProbability > 0.8f) { + profileOperand = OPT_BranchProfileOperand.always(); + condBlock.setInfrequent(); + } + else if (skipProbability > 0.5f) { + profileOperand = OPT_BranchProfileOperand.likely(); + condBlock.setInfrequent(); + } + else if (skipProbability < 0.2f) { + profileOperand = OPT_BranchProfileOperand.never(); + } + else { + profileOperand = OPT_BranchProfileOperand.unlikely(); + } } - else if (skipProbability > 0.8f) { - profileOperand = OPT_BranchProfileOperand.always(); - } - else if (skipProbability > 0.5f) { - profileOperand = OPT_BranchProfileOperand.likely(); - } - else if (skipProbability < 0.2f) { - profileOperand = OPT_BranchProfileOperand.never(); - } else { - profileOperand = OPT_BranchProfileOperand.unlikely(); + profileOperand = new OPT_BranchProfileOperand(); } switch (condition) { @@ -2208,8 +2216,22 @@ //rotation = (address & 0x3) * 8 arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address.copy(), new OPT_IntConstantOperand(0x3))); + + OPT_BasicBlock remainderBlock = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock rotationBlock = arm2ir.createBlockAfterCurrent(); + + //do we actually have to perform the rotation? + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), rotation.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), rotationBlock.makeJumpTarget(), OPT_BranchProfileOperand.never())); + arm2ir.appendInstruction(Goto.create(GOTO, remainderBlock.makeJumpTarget())); + + //in case we are performing the rotation... + arm2ir.setCurrentBlock(rotationBlock); + rotationBlock.setInfrequent(); arm2ir.appendInstruction(Binary.create(INT_SHL, rotation.copyRO(), rotation.copy(), new OPT_IntConstantOperand(3))); arm2ir.appendRotateRight(value.copyRO(), value.copy(), rotation.copy()); + + //continue with the remainder of the instruction + arm2ir.setCurrentBlock(remainderBlock); //allow further usage of the memory address address = adrCopy; @@ -2284,6 +2306,7 @@ arm2ir.appendBranch(arm2ir.getRegister(i.Rd), lazy, BranchType.INDIRECT_BRANCH); } } + public Condition getCondition() { return i.condition; Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-06 15:23:44 UTC (rev 157) +++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-06 15:25:12 UTC (rev 158) @@ -158,7 +158,7 @@ /** * This variable is being set by a call to {@link #printTraceAfterCompletion()} and notifies * the system that the current trace shall be printed, after it has been completed. */ - private boolean requestPrintTrace; + private boolean printTraceAfterCompletionRequested; /** Map to locate HIR basic blocks to re-use translation within a trace */ protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; @@ -248,7 +248,7 @@ * debug purposes. */ protected void printTraceAfterCompletion() { - requestPrintTrace = true; + printTraceAfterCompletionRequested = true; } /** This is the main loop, which generates the HIR. */ @@ -263,7 +263,10 @@ while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) { // Resolve all open direct branches first - resolveAllDirectBranches(); + do { + resolveAllDirectBranches(); + } + while (unresolvedDirectBranches.size() > 0); // Resolve unresolved dynamic jumps resolveAllDynamicBranches(); @@ -276,14 +279,24 @@ eliminateRegisterFills(getUnusedRegisters()); } - if (requestPrintTrace) { - requestPrintTrace = false; + if (printTraceAfterCompletionRequested) { + printTraceAfterCompletionRequested = false; printNextBlocks(preFillBlock, 50); } - - // TODO: maximizeBasicBlocks() } + /* + protected final void maximizeBasicBlocks(OPT_IR ir) { + for (OPT_BasicBlock currBB = ir.cfg.firstInCodeOrder(); currBB != null;) { + if (currBB.mergeFallThrough(ir)) { + // don't advance currBB; it may have a new trivial fallthrough to + // swallow + } else { + currBB = currBB.nextBasicBlockInCodeOrder(); + } + } + }*/ + /** * Translate a sequence of instructions upto an instruction that doesn't know * its immediate/default successor. The currentBlock should be an empty basic This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-08-14 15:32:08
|
Revision: 164 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=164&view=rev Author: michael_baer Date: 2007-08-14 08:32:09 -0700 (Tue, 14 Aug 2007) Log Message: ----------- - Various smaller performance fixes - Added functions to inline a call to CodeTranslator Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/decoder/CodeTranslator.java src/org/binarytranslator/generic/execution/StagedEmulationController.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/DBT_Options.java 2007-08-14 15:32:09 UTC (rev 164) @@ -108,6 +108,9 @@ /** Print out messages from the memory system */ public static boolean debugMemory = false; + + /** Inline calls to descendents of callbased memory? */ + public static boolean inlineCallbasedMemory = false; /** The user ID for the user running the command */ public final static int UID = 1000; @@ -184,7 +187,7 @@ ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value); } else if (key.equalsIgnoreCase("flagEvaluation")) { ARM_Options.flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value); - } else if (key.equalsIgnoreCase("inlining")) { + } else if (key.equalsIgnoreCase("inline")) { ARM_Options.inlining = ARM_Options.InliningBehaviour.valueOf(value); } else { @@ -229,6 +232,8 @@ saveProfileToFile = value; } else if (key.equalsIgnoreCase("minTraceValue")) { minTraceValue = Integer.parseInt(value); + } else if (key.equalsIgnoreCase("inlineCallbasedMemory")) { + inlineCallbasedMemory = Boolean.parseBoolean(value); } else { throw new Error("Unknown DBT option: " + key); Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/Main.java 2007-08-14 15:32:09 UTC (rev 164) @@ -85,6 +85,10 @@ System.err.println("The specified executable '" + DBT_Options.executableFile + "' could not be found."); return; } + + if (DBT.VerifyAssertions) { + System.err.println("WARNING: Assertions are enabled."); + } try { report("Loading " + DBT_Options.executableFile); Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-14 15:32:09 UTC (rev 164) @@ -477,12 +477,27 @@ else return super.inlineBranchInstruction(targetPc, jump); + case FunctionCalls: + if (jump.type == BranchType.CALL) + return true; + else + return super.inlineBranchInstruction(targetPc, jump); + + case FunctionReturns: + if (jump.type == BranchType.CALL) + return true; + else + return super.inlineBranchInstruction(targetPc, jump); + case Functions: if (jump.type == BranchType.CALL || jump.type == BranchType.RETURN) return true; else return super.inlineBranchInstruction(targetPc, jump); + case All: + return true; + default: throw new RuntimeException("Unexpected inlining type."); } @@ -782,6 +797,9 @@ * The operand which is to be rotated. * @param rotation * The amount of rotation that is to be applied to the operand. + * + * @param inline + * Shall the invokation of this rotate right be inlined? */ public void appendRotateRight(OPT_RegisterOperand result, OPT_Operand rotatedOperand, OPT_Operand rotation) { VM_TypeReference IntegerType = VM_TypeReference Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-14 15:32:09 UTC (rev 164) @@ -374,7 +374,7 @@ /** The successor of this instruction, if the condition evaluates to false.*/ private final int conditionFalseSuccessor; - /** The address of the successor of this instrction if it is constant, otherwise -1. */ + /** The address of the successor of this instruction if it is constant, otherwise -1. */ private final int successorInstruction; /** The address of this instruction. */ @@ -406,7 +406,10 @@ } if (successorInstruction != -1) { - ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor); + if (conditionTrueSuccessor == conditionFalseSuccessor) + ps.branchInfo.profileBranch(instructionAddress, instructionAddress); + else + ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor); } } else { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-14 15:32:09 UTC (rev 164) @@ -10,7 +10,10 @@ public enum InliningBehaviour { Default, Functions, - DynamicJumps + FunctionCalls, + FunctionReturns, + DynamicJumps, + All, } /** Set to true to enable a fastpath for the decoding of data processing instructions.. */ @@ -22,5 +25,6 @@ /** This variable describes, if the translated program shall be optimized using lazy evaluation.*/ public static FlagBehaviour flagEvaluation = FlagBehaviour.Lazy; + /** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */ public static InliningBehaviour inlining = InliningBehaviour.Default; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-14 15:32:09 UTC (rev 164) @@ -764,7 +764,7 @@ */ private float getSkipProbability() { - if (ARM_Options.optimizeTranslationByProfiling) + if (!ARM_Options.optimizeTranslationByProfiling) return -1f; return ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4)); @@ -1279,7 +1279,7 @@ } } - /** Subtract. <code>Rd = op1 - op2 </code>.*/ + /** Subtract. <code>Rd = op1 - op2</code>.*/ private final class DataProcessing_Sub extends DataProcessing { public DataProcessing_Sub(ARM_Instructions.DataProcessing instr) { Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-14 15:32:09 UTC (rev 164) @@ -48,6 +48,18 @@ /** The directory in which temporary files are created. Note that the path is expected to end with a path delimiter.*/ private final static String TEMP_FILE_DIR = "/tmp/"; + /** The first address on the heap. */ + private int heapBegin; + + /** The last address on the heap. */ + private int heapEnd; + + /** The first address on the stack. */ + private int stackBegin; + + /** The last address on the stack*/ + private int stackEnd; + /** The file handle that is distributed with the next call to {@link #addFile(RandomAccessFile)}. * Valid Angle handles are non-zero values (i.e. >= 1).*/ private int nextFileHandle = 1; @@ -55,7 +67,7 @@ /** */ private AngelSystemCall[] sysCalls; - public AngelSystemCalls(ARM_ProcessSpace ps) { + public AngelSystemCalls(ARM_ProcessSpace ps, int heapBegin, int heapEnd, int stackBegin, int stackEnd) { this.ps = ps; sysCalls = new AngelSystemCall[0x32]; @@ -84,6 +96,12 @@ sysCalls[0x18] = new Sys_Exit(); sysCalls[0x30] = new Sys_Elapsed(); sysCalls[0x31] = new Sys_TickFreq(); + + this.heapBegin = heapBegin; + this.heapEnd = heapEnd; + + this.stackBegin = stackBegin; + this.stackEnd = stackEnd; } public void doSysCall(int callNum) { @@ -128,7 +146,7 @@ } } - private interface AngelFileStream { + private static interface AngelFileStream { boolean isTty(); int getLength(); @@ -143,7 +161,7 @@ void seek(long pos) throws IOException; } - private class ConsoleStream implements AngelFileStream { + private static class ConsoleStream implements AngelFileStream { private String previousInputLine = null; @@ -203,7 +221,7 @@ } } - private class FileStream implements AngelFileStream { + private static class FileStream implements AngelFileStream { private final RandomAccessFile file; @@ -630,11 +648,11 @@ String cmdLine = DBT_Options.executableFile; - if (cmdLine.contains(" ")) + if (cmdLine.contains(" ") && !cmdLine.contains("\"")) cmdLine = '"' + cmdLine + '"'; for(String s : DBT_Options.executableArguments) { - if (s.contains(" ")) { + if (s.contains(" ") && !s.contains("\"")) { s = '"' + s + '"'; } @@ -659,10 +677,10 @@ int ptrParamBlock = ps.registers.get(1); //return that we couldn't calculate any of the requested heap size values - ps.memory.store32(ptrParamBlock, 0); - ps.memory.store32(ptrParamBlock + 4, 0); - ps.memory.store32(ptrParamBlock + 8, 0); - ps.memory.store32(ptrParamBlock + 12, 0); + ps.memory.store32(ptrParamBlock, heapBegin); + ps.memory.store32(ptrParamBlock + 4, heapEnd); + ps.memory.store32(ptrParamBlock + 8, stackBegin); + ps.memory.store32(ptrParamBlock + 12, stackEnd); } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -9,7 +9,7 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Interpreter; -import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.memory.IntAddressedMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; @@ -38,7 +38,7 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new ByteAddressedMemory(); + memory = new IntAddressedMemory(); } /** @@ -49,6 +49,7 @@ * the generation context for the HIR generation * @return a HIR generator */ + @Override public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new ARM2IR(context, trace); } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -1,26 +1,55 @@ package org.binarytranslator.arch.arm.os.process.image; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions; import org.binarytranslator.arch.arm.os.abi.semihosting.AngelSystemCalls; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.generic.execution.GdbController.GdbTarget; -import org.binarytranslator.generic.memory.AutoMappingMemory; +import org.binarytranslator.generic.fault.InsufficientMemoryException; import org.binarytranslator.generic.os.loader.Loader; public class ARM_ImageProcessSpace extends ARM_ProcessSpace { - private AngelSystemCalls sysCalls = new AngelSystemCalls(this); + private AngelSystemCalls sysCalls; + private final int STACK_SIZE = 4096 * 10; + private final int HEAP_SIZE = 4096 * 10; public ARM_ImageProcessSpace() { super(); //make sure that pages of memory are automatically mapped in as they are requested. - memory = new AutoMappingMemory(memory); + //memory = new AutoMappingMemory(memory); } + private int allocateFreeMemoryArea(int stackSize) throws InsufficientMemoryException + { + int pagesize = memory.getPageSize(); + int stackStart = -1; + int checkedAddress = stackStart; + + while (checkedAddress < 0 || checkedAddress > pagesize) { + if (memory.isMapped(checkedAddress)) { + //we cannot extend the stack into this page + stackStart = checkedAddress - pagesize; + } + else { + int stackspace = Math.abs(stackStart - checkedAddress) + pagesize; + + if (stackspace >= stackSize) { + memory.ensureMapped(stackStart - stackSize + 1, stackStart); + return stackStart - stackSize + 1; + } + } + + checkedAddress -= pagesize; + } + + throw new InsufficientMemoryException(this, "Allocate free memory area for ARM stack and heap."); + } + @Override public void doSysCall() { @@ -91,6 +120,15 @@ @Override public void initialise(Loader loader) { registers.set(ARM_Registers.PC, loader.getEntryPoint()); + int stackBegin = allocateFreeMemoryArea(STACK_SIZE); + int heapBegin = allocateFreeMemoryArea(HEAP_SIZE); + + if (DBT_Options.debugMemory || DBT_Options.debugLoader) { + System.out.println(String.format("Placing ARM Heap from 0x%x to 0x%x.", heapBegin, heapBegin + HEAP_SIZE - 1)); + System.out.println(String.format("Placing ARM Stack from 0x%x to 0x%x.", stackBegin, stackBegin + STACK_SIZE - 1)); + } + + sysCalls = new AngelSystemCalls(this, heapBegin, heapBegin + HEAP_SIZE, stackBegin, stackBegin + STACK_SIZE); } } Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-08-14 15:32:09 UTC (rev 164) @@ -29,6 +29,7 @@ import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.compilers.opt.ir.OPT_IR; import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand; import org.jikesrvm.compilers.opt.ir.OPT_Operators; @@ -272,6 +273,18 @@ report("CFG at end of constructor:\n" + gc.cfg); } } + + /** + * Should a trace follow a branch and link instruction or should it terminate + * the trace? + * + * @param pc + * the address of the branch and link instruction + * @return whether the trace should continue + */ + public boolean traceContinuesAfterBranchAndLink(int pc) { + return shallTraceStop() == false; + } /** * Translate the instruction at the given pc Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -140,6 +140,7 @@ * the generation context for the HIR generation * @return a HIR generator */ + @Override public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new PPC2IR(context, trace); } Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -12,7 +12,6 @@ import java.util.Hashtable; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; - import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; @@ -149,6 +148,7 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ + @Override public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new X862IR(context, trace); } Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-14 15:32:09 UTC (rev 164) @@ -29,6 +29,7 @@ import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.OPT_Constants; +import org.jikesrvm.compilers.opt.OPT_InlineDecision; import org.jikesrvm.compilers.opt.ir.Athrow; import org.jikesrvm.compilers.opt.ir.BBend; import org.jikesrvm.compilers.opt.ir.Call; @@ -45,6 +46,7 @@ import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.compilers.opt.ir.OPT_Inliner; import org.jikesrvm.compilers.opt.ir.OPT_Instruction; import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; @@ -130,7 +132,7 @@ public final ProcessSpace ps; /** The VM method's generation context. */ - protected OPT_GenerationContext gc; + protected final OPT_GenerationContext gc; /** The OPT_BasicBlock in which instructions are currently being inserted */ protected OPT_BasicBlock currentBlock; @@ -208,7 +210,7 @@ * @param context * The JRVM generation context for this trace. */ - protected CodeTranslator(OPT_GenerationContext context, + protected CodeTranslator(OPT_GenerationContext context, DBT_Trace trace) { // Store the trace that we're invoked from @@ -284,7 +286,12 @@ printNextBlocks(preFillBlock, 50); } + try { ((DBT_Trace) gc.method).setNumberOfInstructions(numberOfInstructions); + } + catch (ClassCastException e) { + System.err.println("Error casting " + gc.method + " to DBT_Trace."); + } } @@ -531,7 +538,7 @@ /** * Get the generation context. */ - public OPT_GenerationContext getGenerationContext() { + public final OPT_GenerationContext getGenerationContext() { return gc; } @@ -545,7 +552,7 @@ * @param hirBlock * The block that is to be registered. */ - protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { + protected final void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { blockMap.put(lazy.makeKey(pc), hirBlock); } @@ -559,7 +566,7 @@ * The lazy state assumed within the returned trace. * @return An appropriate basic block or null if no translation exists. */ - protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { + protected final OPT_BasicBlock findMapping(int pc, Laziness lazy) { return blockMap.get(lazy.makeKey(pc)); } @@ -757,13 +764,24 @@ * within the code cache c) The trace is already too long d) the branch is * supposedly a CALL or RETURN */ + + boolean decision = DBT_Options.singleInstrTranslation == false && jump.type == BranchType.DIRECT_BRANCH && !shallTraceStop(); + if (!decision) { + + if (DBT_Options.debugBranchResolution) { + String text = (!decision ? "Not inlining " : "Inlining "); + text += jump.type + " to 0x" + Integer.toHexString(targetPc); + System.out.println(text); + } + + return false; + } + + //only query the code cache if we have to DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc); + decision = (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) ; - boolean decision = DBT_Options.singleInstrTranslation == false - && (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) && !shallTraceStop() - && jump.type != BranchType.CALL && jump.type != BranchType.RETURN; - if (DBT_Options.debugBranchResolution) { String text = (!decision ? "Not inlining " : "Inlining "); text += jump.type + " to 0x" + Integer.toHexString(targetPc); @@ -967,18 +985,6 @@ } /** - * Should a trace follow a branch and link instruction or should it terminate - * the trace? - * - * @param pc - * the address of the branch and link instruction - * @return whether the trace should continue - */ - public boolean traceContinuesAfterBranchAndLink(int pc) { - return shallTraceStop() == false; - } - - /** * Load all the registers from the ProcessSpace into the pre-fill block */ private void preFillAllRegisters() { @@ -1169,6 +1175,7 @@ if (intTemps == null) { intTemps = new OPT_Register[10]; } + OPT_Register result = intTemps[num]; if (result == null) { OPT_RegisterOperand regOp = gc.temps.makeTempInt(); @@ -1459,7 +1466,60 @@ callInstruction.bcIndex = trace.registerDynamicLink(methodRef, callType); appendInstruction(callInstruction); } + + /** + * Execute an inlining decision inlDec for the CALL instruction + * callSite that is contained in ir. + * + * @param inlDec the inlining decision to execute + * @param ir the governing IR + * @param callSite the call site to inline + */ + public void appendInlinedCall(OPT_Instruction callSite) { + + if (DBT.VerifyAssertions) + DBT._assert(Call.conforms(callSite)); + + OPT_BasicBlock next = createBlockAfterCurrent(); + + //Find out where the call site is and isolate it in its own basic block. + currentBlock = createBlockAfterCurrent(); + currentBlock.appendInstruction(callSite); + + OPT_BasicBlock in = currentBlock.prevBasicBlockInCodeOrder(); + OPT_BasicBlock out = currentBlock.nextBasicBlockInCodeOrder(); + + // Clear the sratch object of any register operands being + // passed as parameters. + // BC2IR uses this field for its own purposes, and will be confused + // if the scratch object has been used by someone else and not cleared. + for (int i = 0; i < Call.getNumberOfParams(callSite); i++) { + OPT_Operand arg = Call.getParam(callSite, i); + if (arg instanceof OPT_RegisterOperand) { + ((OPT_RegisterOperand) arg).scratchObject = null; + } + } + // Execute the inlining decision, updating ir.gc's state. + OPT_InlineDecision inlDec = OPT_InlineDecision.YES(Call.getMethod(callSite).getTarget(), ""); + OPT_GenerationContext childgc = OPT_Inliner.execute(inlDec, gc, null, callSite); + + // Splice the callee into the caller's code order + gc.cfg.removeFromCFGAndCodeOrder(currentBlock); + gc.cfg.breakCodeOrder(in, out); + gc.cfg.linkInCodeOrder(in, childgc.cfg.firstInCodeOrder()); + gc.cfg.linkInCodeOrder(childgc.cfg.lastInCodeOrder(), out); + + // Splice the callee into the caller's CFG + in.insertOut(childgc.prologue); + + if (childgc.epilogue != null) { + childgc.epilogue.insertOut(out); + } + + currentBlock = next; + } + /** Report some debug output */ protected abstract void report(String str); @@ -1470,8 +1530,7 @@ * Plant instructions modifying a lazy state into one with no laziness * * @param laziness - * the laziness to modify - */ + * the laziness to modify */ public abstract void resolveLaziness(Laziness laziness); /** @@ -1481,20 +1540,17 @@ * the status of the lazy evaluation * @param pc * the program counter for the instruction - * @return the next instruction address or -1 - */ + * @return the next instruction address or -1 */ protected abstract int translateInstruction(Laziness lazy, int pc); /** * Fill all the registers from the ProcessSpace, that is take the register - * values from the process space and place them in the traces registers. - */ + * values from the process space and place them in the traces registers. */ protected abstract void fillAllRegisters(); /** * Spill all the registers, that is put them from the current running trace - * into the process space - */ + * into the process space. */ protected abstract void spillAllRegisters(); /** Return an array of unused registers */ Modified: src/org/binarytranslator/generic/execution/StagedEmulationController.java =================================================================== --- src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-14 15:32:09 UTC (rev 164) @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.TreeMap; import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; @@ -38,7 +39,7 @@ } /** Maps a dynamic basic block to the address of the first instruction within that block. */ - private final HashMap<Integer, DynamicBasicBlock> traceCache = new HashMap<Integer, DynamicBasicBlock>(); + private final TreeMap<Integer, DynamicBasicBlock> traceCache = new TreeMap<Integer, DynamicBasicBlock>(); /** The interpreter that is used to perform the actual execution of single instructions. */ private final Interpreter interpreter; @@ -70,10 +71,13 @@ //No, so stop and create a trace from the decoded instructions DynamicBasicBlock newTrace = new DynamicBasicBlock(instructions); - if (instructions.size() > 3) { +// add this trace to the trace cache + traceCache.put(traceStart, newTrace); + + /*if (instructions.size() > 3) { //add this trace to the trace cache, if it contains enough instructions traceCache.put(traceStart, newTrace); - } + }*/ return newTrace; } @@ -94,6 +98,8 @@ trace.compiledTrace = new DBT_Trace(ps, pc); trace.compiledTrace.compile(); trace.instructions = null; + + ps.codeCache.add(pc, trace.compiledTrace); } /** Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-14 15:32:09 UTC (rev 164) @@ -99,7 +99,7 @@ /** * A translation helper for generating code */ - protected CodeTranslator helper; + protected CodeTranslator translator; /** * The generation context we're translating within @@ -162,7 +162,7 @@ * page table into a register */ public void initTranslate(CodeTranslator helper) { - this.helper = helper; + this.translator = helper; this.gc = helper.getGenerationContext(); OPT_RegisterOperand memoryOp = helper.makeTemp(memoryType); helper.appendInstruction(GetField.create(GETFIELD, memoryOp, @@ -187,21 +187,27 @@ */ private void translateLoad(VM_Method loadMethod, int bcIndex, OPT_Operand addr, OPT_RegisterOperand dest) { - OPT_Instruction s = Call.create(CALL, dest, null, null, null, 2); + OPT_Instruction s = Call.create(CALL, dest.copyRO(), null, null, null, 2); VM_MethodReference loadMethRef = loadMethod.getMemberRef() .asMethodReference(); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(loadMethRef, - loadMethod); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(loadMethRef, loadMethod); OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType); Call.setParam(s, 0, memoryOp); // Sets 'this' pointer - Call.setParam(s, 1, addr); + Call.setParam(s, 1, addr.copy()); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, new OPT_AddressConstantOperand(loadMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = bcIndex; - helper.appendInstruction(s); + + if (DBT_Options.inlineCallbasedMemory) { + translator.appendInlinedCall(s); + } + else + { + s.position = gc.inlineSequence; + s.bcIndex = bcIndex; + translator.appendInstruction(s); + } } /** @@ -335,14 +341,21 @@ storeMethod); OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType); Call.setParam(s, 0, memoryOp); // Sets 'this' pointer - Call.setParam(s, 1, addr); - Call.setParam(s, 2, src); + Call.setParam(s, 1, addr.copy()); + Call.setParam(s, 2, src.copy()); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, new OPT_AddressConstantOperand(storeMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = bcIndex; - helper.appendInstruction(s); + + if (DBT_Options.inlineCallbasedMemory) { + translator.appendInlinedCall(s); + } + else + { + s.position = gc.inlineSequence; + s.bcIndex = bcIndex; + translator.appendInstruction(s); + } } /** Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-14 15:32:09 UTC (rev 164) @@ -14,6 +14,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.fault.SegmentationFault; import org.jikesrvm.VM_Configuration; +import org.vmmagic.pragma.Inline; /** * IntAddressedMemory: @@ -85,6 +86,7 @@ /** * Return the offset part of the address */ + @Inline protected int getOffset(int address) { return (address & (PAGE_SIZE - 1)) >>> 2; } @@ -92,6 +94,7 @@ /** * Return the page table entry part of the address */ + @Inline private static final int getPTE(int address) { return address >>> OFFSET_BITS; } @@ -311,9 +314,10 @@ MemoryMapException.unalignedAddress(addr); } // Check file offset is page aligned - if ((offset % PAGE_SIZE) != 0) { + /*if ((offset % PAGE_SIZE) != 0) { MemoryMapException.unalignedFileOffset(offset); - } + }*/ + if (DBT_Options.debugRuntime) { System.out.println("Mapping file " + file + " offset=" + offset + " addr=0x" + Integer.toHexString(addr) + " len=" + len Modified: src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-08-14 15:32:09 UTC (rev 164) @@ -420,29 +420,29 @@ // Extract the memory page number from addr. OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp, + translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp, addr, new OPT_IntConstantOperand(OFFSET_BITS))); // Extract the location of the address within the page. OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, offsetRegOp, + translator.appendInstruction(Binary.create(INT_AND, offsetRegOp, addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1))); - helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp + translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp .copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2))); // Retrieve the int[] for the correct page into pageReg. OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg, VM_TypeReference.IntArray); - helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, + translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, new OPT_RegisterOperand(readableMemoryReg, VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(), new OPT_LocationOperand(VM_TypeReference.IntArray), new OPT_TrueGuardOperand())); // Copy to reg from the correct array element. - helper.appendInstruction(ALoad.create(INT_ALOAD, dest, + translator.appendInstruction(ALoad.create(INT_ALOAD, dest, pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand( VM_TypeReference.Int), new OPT_TrueGuardOperand())); } @@ -461,15 +461,15 @@ // Load as 32-bit then mask out what we need translateAlignedLoad32(addr, dest); // addr = (addr & 0x3) * 8 - helper.appendInstruction(Binary.create(INT_AND, + translator.appendInstruction(Binary.create(INT_AND, addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3))); - helper.appendInstruction(Binary.create(INT_SHL, + translator.appendInstruction(Binary.create(INT_SHL, addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3))); // rD <<= addr - helper.appendInstruction(Binary.create(INT_SHL, + translator.appendInstruction(Binary.create(INT_SHL, dest.copyRO(), dest.copyRO(), addr.copyRO())); // rD >>>= 24 - helper.appendInstruction(Binary.create(INT_USHR, dest + translator.appendInstruction(Binary.create(INT_USHR, dest .copyRO(), dest.copyRO(), new OPT_IntConstantOperand(24))); } @@ -487,17 +487,17 @@ // Load as 32-bit then mask out what we need translateAlignedLoad32(addr, dest); // addr = (3 - (addr & 0x3)) * 8 - helper.appendInstruction(Binary.create(INT_AND, + translator.appendInstruction(Binary.create(INT_AND, addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3))); - helper.appendInstruction(Binary.create(INT_SUB, + translator.appendInstruction(Binary.create(INT_SUB, addr.copyRO(), new OPT_IntConstantOperand(3), addr.copyRO())); - helper.appendInstruction(Binary.create(INT_SHL, + translator.appendInstruction(Binary.create(INT_SHL, addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3))); // rD >>>= addr - helper.appendInstruction(Binary.create(INT_USHR, dest + translator.appendInstruction(Binary.create(INT_USHR, dest .copyRO(), dest.copyRO(), addr.copyRO())); // rD &= 0xff - helper.appendInstruction(Binary.create(INT_AND, + translator.appendInstruction(Binary.create(INT_AND, dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(0xff))); } @@ -514,43 +514,43 @@ OPT_RegisterOperand dest) { // The block after this load - NB could still need to plant an update for // this instruction in here - OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent(); + OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent(); // Put call based version for (addr & 3 == 3) in aligned3 - OPT_BasicBlock aligned3 = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned3 = translator.createBlockAfterCurrent(); // Put all other cases in aligned - OPT_BasicBlock aligned = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned = translator.createBlockAfterCurrent(); // Compute tempReg = addr & 3 OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, tempRegOp, + translator.appendInstruction(Binary.create(INT_AND, tempRegOp, addr.copyRO(), new OPT_IntConstantOperand(0x3))); // Create if (addr & 3) == 3 goto aligned3 - helper.appendInstruction(IfCmp.create(INT_IFCMP, null, + translator.appendInstruction(IfCmp.create(INT_IFCMP, null, tempRegOp.copyRO(), new OPT_IntConstantOperand(0x3), - OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), helper + OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), translator .getConditionalBranchProfileOperand(false))); - helper.getCurrentBlock().insertOut(aligned3); + translator.getCurrentBlock().insertOut(aligned3); // Create aligned code - helper.setCurrentBlock(aligned); + translator.setCurrentBlock(aligned); translateAlignedLoad32(addr, dest); // tempReg = (addr & 0x3) * 8 - helper.appendInstruction(Binary.create(INT_SHL, tempRegOp + translator.appendInstruction(Binary.create(INT_SHL, tempRegOp .copyRO(), tempRegOp.copyRO(), new OPT_IntConstantOperand(3))); // rD <<= tempReg - helper.appendInstruction(Binary.create(INT_SHL, + translator.appendInstruction(Binary.create(INT_SHL, dest.copyRO(), dest.copyRO(), tempRegOp.copyRO())); // rD >>= 16 - helper.appendInstruction(Binary.create(INT_SHR, + translator.appendInstruction(Binary.create(INT_SHR, dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(16))); - helper.appendInstruction(Goto.create(GOTO, nextBlock + translator.appendInstruction(Goto.create(GOTO, nextBlock .makeJumpTarget())); aligned.deleteNormalOut(); aligned.insertOut(nextBlock); // Create aligned3 code - helper.setCurrentBlock(aligned3); + translator.setCurrentBlock(aligned3); translateCallBasedLoadSigned16(addr.copyRO(), dest.copyRO()); // Move to empty block for rest of load instruction - helper.setCurrentBlock(nextBlock); + translator.setCurrentBlock(nextBlock); } /** @@ -566,45 +566,45 @@ OPT_RegisterOperand dest) { // The block after this load - NB could still need to plant an update for // this instruction in here - OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent(); + OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent(); // Put call based version for (addr & 3 == 3) in aligned3 - OPT_BasicBlock aligned3 = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned3 = translator.createBlockAfterCurrent(); // Put all other cases in aligned - OPT_BasicBlock aligned = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned = translator.createBlockAfterCurrent(); // Compute tempReg = addr & 3 OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, tempRegOp, + translator.appendInstruction(Binary.create(INT_AND, tempRegOp, addr.copyRO(), new OPT_IntConstantOperand(0x3))); // Create if (addr & 3) == 3 goto aligned3 - helper.appendInstruction(IfCmp.create(INT_IFCMP, null, + translator.appendInstruction(IfCmp.create(INT_IFCMP, null, tempRegOp.copyRO(), new OPT_IntConstantOperand(0x3), - OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), helper + OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), translator .getConditionalBranchProfileOperand(false))); - helper.getCurrentBlock().insertOut(aligned3); + translator.getCurrentBlock().insertOut(aligned3); // Create aligned code - helper.setCurrentBlock(aligned); + translator.setCurrentBlock(aligned); translateAlignedLoad32(addr, dest); // tempReg = (2 - (addr & 0x3)) * 8 - helper.appendInstruction(Binary.create(INT_SUB, tempRegOp + translator.appendInstruction(Binary.create(INT_SUB, tempRegOp .copyRO(), new OPT_IntConstantOperand(2), tempRegOp.copyRO())); - helper.appendInstruction(Binary.create(INT_SHL, tempRegOp + translator.appendInstruction(Binary.create(INT_SHL, tempRegOp .copyRO(), tempRegOp.copyRO(), new OPT_IntConstantOperand(3))); // rD >>>= tempReg - helper.appendInstruction(Binary.create(INT_USHR, dest + translator.appendInstruction(Binary.create(INT_USHR, dest .copyRO(), dest.copyRO(), tempRegOp.copyRO())); // rD &= 0xffff - helper.appendInstruction(Binary.create(INT_AND, + translator.appendInstruction(Binary.create(INT_AND, dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(0xffff))); - helper.appendInstruction(Goto.create(GOTO, nextBlock + translator.appendInstruction(Goto.create(GOTO, nextBlock .makeJumpTarget())); aligned.deleteNormalOut(); aligned.insertOut(nextBlock); // Create aligned3 code - helper.setCurrentBlock(aligned3); + translator.setCurrentBlock(aligned3); translateCallBasedLoadUnsigned16(addr.copyRO(), dest.copyRO()); // Move to empty block for rest of load instruction - helper.setCurrentBlock(nextBlock); + translator.setCurrentBlock(nextBlock); } /** @@ -618,34 +618,34 @@ public void translateLoad32(OPT_RegisterOperand addr, OPT_RegisterOperand dest) { // The block after this load - NB could still need to plant an update for // this instruction in here - OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent(); + OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent(); // Put call based version for (addr & 3 != 0) in aligned123 - OPT_BasicBlock aligned123 = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned123 = translator.createBlockAfterCurrent(); // Put case (addr & 3 == 0) in aligned - OPT_BasicBlock aligned = helper.createBlockAfterCurrent(); + OPT_BasicBlock aligned = translator.createBlockAfterCurrent(); // Compute tempReg = addr & 3 OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, tempRegOp, + translator.appendInstruction(Binary.create(INT_AND, tempRegOp, addr.copyRO(), new OPT_IntConstantOperand(0x3))); // Create if (addr & 3) == 3 goto aligned3 - helper.appendInstruction(IfCmp.create(INT_IFCMP, null, + translator.appendInstruction(IfCmp.create(INT_IFCMP, null, tempRegOp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand - .NOT_EQUAL(), aligned123.makeJumpTarget(), helper + .NOT_EQUAL(), aligned123.makeJumpTarget(), translator .getConditionalBranchProfileOperand(false))); - helper.getCurrentBlock().insertOut(aligned123); + translator.getCurrentBlock().insertOut(aligned123); // Create aligned code - helper.setCurrentBlock(aligned); + translator.setCurrentBlock(aligned); translateAlignedLoad32(addr, dest); - helper.appendInstruction(Goto.create(GOTO, nextBlock + translator.appendInstruction(Goto.create(GOTO, nextBlock .makeJumpTarget())); aligned.deleteNormalOut(); aligned.insertOut(nextBlock); // Create aligned3 code - helper.setCurrentBlock(aligned123); + translator.setCurrentBlock(aligned123); translateCallBasedLoad32(addr.copyRO(), dest.copyRO()); // Move to empty block for rest of load instruction - helper.setCurrentBlock(nextBlock); + translator.setCurrentBlock(nextBlock); } /** @@ -662,29 +662,29 @@ // Extract the memory page number from addr. OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp, + translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp, addr, new OPT_IntConstantOperand(OFFSET_BITS))); // Extract the location of the address within the page. OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, offsetRegOp, + translator.appendInstruction(Binary.create(INT_AND, offsetRegOp, addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1))); - helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp + translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp .copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2))); // Retrieve the int[] for the correct page into pageReg. OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg, VM_TypeReference.IntArray); - helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, + translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, new OPT_RegisterOperand(writableMemoryReg, VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(), new OPT_LocationOperand(VM_TypeReference.IntArray), new OPT_TrueGuardOperand())); // Copy to reg from the correct array element. - helper.appendInstruction(ALoad.create(INT_ALOAD, dest, + translator.appendInstruction(ALoad.create(INT_ALOAD, dest, pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand( VM_TypeReference.Int), new OPT_TrueGuardOperand())); } @@ -703,29 +703,29 @@ // Extract the memory page number from addr. OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp, + translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp, addr, new OPT_IntConstantOperand(OFFSET_BITS))); // Extract the location of the address within the page. OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg, VM_TypeReference.Int); - helper.appendInstruction(Binary.create(INT_AND, offsetRegOp, + translator.appendInstruction(Binary.create(INT_AND, offsetRegOp, addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1))); - helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp + translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp .copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2))); // Retrieve the int[] for the correct page into pageReg. OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg, VM_TypeReference.IntArray); - helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, + translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp, new OPT_RegisterOperand(writableMemoryReg, VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(), new OPT_LocationOperand(VM_TypeReference.IntArray), new OPT_TrueGuardOperand())); // Copy to reg from the correct array element. - helper.appendInstruction(ALoad.create(INT_ASTORE, src, + translator.appendInstruction(ALoad.create(INT_ASTORE, src, pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand( VM_TypeReference.Int), new OPT_TrueGuardOperand())); } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-14 15:32:09 UTC (rev 164) @@ -215,7 +215,7 @@ public static boolean conforms(String filename) { RandomAccessFile rFile = null; - report("Testing is file is ELF: " + filename); + report("Testing if file is ELF: " + filename); try { rFile = new RandomAccessFile(filename, "r"); Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -70,8 +70,7 @@ * @param trace * @return a HIR generator */ - public abstract CodeTranslator createTranslator( - OPT_GenerationContext context, DBT_Trace trace) throws UnsupportedOperationException ; + public abstract CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) throws UnsupportedOperationException ; /** * Returns an instance of {@link Interpreter} that can be used to interpret instructions Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-11 11:28:50 UTC (rev 163) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-14 15:32:09 UTC (rev 164) @@ -117,7 +117,7 @@ * This list stores at which bytecode index a specific method call is executed. * The index of an element plus {@link #CUSTOM_CALL_BCINDEX_BASE} equals the bytecode index * for the call.*/ - private List<CustomCallInformation> customCalls = new ArrayList<CustomCallInformation>(); + private final List<CustomCallInformation> customCalls = new ArrayList<CustomCallInformation>(); /** * Create an optimizing compiler HIR code generator for this trace @@ -126,7 +126,9 @@ * the generation context for the HIR generation * @return a HIR generator */ + @Override public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { + return ps.createTranslator(context, this); } @@ -322,7 +324,7 @@ * Size of bytecodes for this method */ public int getBytecodeLength() { - return 256; + return numberOfInstructions == 0 ? 256 : numberOfInstructions; } public int getNumberOfInstructions() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |