Mercurial > hg > truffle
diff graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/cisc/x86/X86TemplateCreator.java @ 3733:e233f5660da4
Added Java files from Maxine project.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 19:59:18 +0100 |
parents | |
children | bc8527f3071c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/cisc/x86/X86TemplateCreator.java Sat Dec 17 19:59:18 2011 +0100 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.max.asm.gen.cisc.x86; + +import java.util.*; + +import com.sun.max.asm.gen.*; +import com.sun.max.lang.*; + +/** + */ +public abstract class X86TemplateCreator<Template_Type extends X86Template> { + + private final Assembly assembly; + private final WordWidth addressWidth; + private X86InstructionDescription instructionDescription; + private InstructionAssessment instructionAssessment; + private X86TemplateContext context; + private int serial = 1; + + protected X86TemplateCreator(Assembly assembly, WordWidth addressWidth) { + this.assembly = assembly; + this.addressWidth = addressWidth; + } + + private final List<Template_Type> templates = new ArrayList<Template_Type>(); + + public List<Template_Type> templates() { + return templates; + } + + private final Map<String, List<Template_Type>> internalNameToTemplates = new HashMap<String, List<Template_Type>>(); + + private void addTemplate(Template_Type template) { + templates.add(template); + List<Template_Type> t = internalNameToTemplates.get(template.internalName()); + if (t == null) { + t = new LinkedList<Template_Type>(); + internalNameToTemplates.put(template.internalName(), t); + } + t.add(template); + } + + private void computeRedundancy(X86Template template) { + final List<Template_Type> t = internalNameToTemplates.get(template.internalName()); + if (t != null) { + for (X86Template other : t) { + if (template.computeRedundancyWith(other)) { + return; + } + } + } + } + + protected abstract Template_Type createTemplate(X86InstructionDescription description, int ser, InstructionAssessment instructionFamily, X86TemplateContext contxt); + + private void createTemplate() { + final Template_Type template = createTemplate(instructionDescription, serial, instructionAssessment, context); + if (X86InstructionDescriptionVisitor.Static.visitInstructionDescription(template, instructionDescription)) { + final InstructionDescription modRMInstructionDescription = template.modRMInstructionDescription(); + if (modRMInstructionDescription != null && !X86InstructionDescriptionVisitor.Static.visitInstructionDescription(template, modRMInstructionDescription)) { + return; + } + computeRedundancy(template); + addTemplate(template); + serial++; + } + } + + private void createTemplatesForSibBaseCases() { + for (X86TemplateContext.SibBaseCase sibBaseCase : X86TemplateContext.SibBaseCase.VALUES) { + if (sibBaseCase == X86TemplateContext.SibBaseCase.GENERAL_REGISTER || context.modCase() == X86TemplateContext.ModCase.MOD_0) { + context = context.clone(); + context.sibBaseCase = sibBaseCase; + createTemplate(); + } + } + } + + private void createTemplatesForSibIndexCases() { + for (X86TemplateContext.SibIndexCase sibIndexCase : X86TemplateContext.SibIndexCase.VALUES) { + context = context.clone(); + context.setSibIndexCase(sibIndexCase); + createTemplatesForSibBaseCases(); + } + } + + private void createTemplatesForRMCases() { + for (X86TemplateContext.RMCase rmCase : X86TemplateContext.RMCase.VALUES) { + context = context.clone(); + context.setRMCase(rmCase); + switch (context.modCase()) { + case MOD_3: { + if (rmCase == X86TemplateContext.RMCase.NORMAL) { + createTemplate(); + } + break; + } + default: { + switch (rmCase) { + case SIB: + createTemplatesForSibIndexCases(); + break; + default: + createTemplate(); + break; + } + } + } + } + } + + private void createTemplatesForModRMGroups() { + if (instructionAssessment.modRMGroup() != null) { + for (ModRMGroup.Opcode modRMGroupOpcode : ModRMGroup.Opcode.VALUES) { + context = context.clone(); + context.setModRMGroupOpcode(modRMGroupOpcode); + createTemplatesForRMCases(); + } + } else { + createTemplatesForRMCases(); + } + } + + private void createTemplatesForModCases(WordWidth operandSizeAttribute) { + context = context.clone(); + context.setOperandSizeAttribute(operandSizeAttribute); + + if (instructionAssessment.hasModRMByte()) { + for (X86TemplateContext.ModCase modCase : X86TemplateContext.ModCase.VALUES) { + context = context.clone(); + context.setModCase(modCase); + createTemplatesForModRMGroups(); + } + } else { + createTemplate(); + } + } + + private void createTemplatesForOperandSizeAttribute(WordWidth addressSizeAttribute) { + context = context.clone(); + context.setAddressSizeAttribute(addressSizeAttribute); + + if (instructionDescription.requiredOperandSize() != null) { + createTemplatesForModCases(instructionDescription.requiredOperandSize()); + } else { + if (instructionDescription.defaultOperandSize() != WordWidth.BITS_64) { + createTemplatesForModCases(WordWidth.BITS_32); + } + if (addressWidth == WordWidth.BITS_64) { + createTemplatesForModCases(WordWidth.BITS_64); + } + if (X86Assembly.are16BitOffsetsSupported() || !instructionAssessment.isJump()) { + createTemplatesForModCases(WordWidth.BITS_16); + } + } + } + + private void createTemplatesForAddressSizeAttribute() { + if (instructionDescription.requiredAddressSize() != null) { + if (X86Assembly.are16BitAddressesSupported() || instructionDescription.requiredAddressSize() == addressWidth) { + createTemplatesForOperandSizeAttribute(instructionDescription.requiredAddressSize()); + } + } else { + createTemplatesForOperandSizeAttribute(addressWidth); + if (X86Assembly.are16BitAddressesSupported() && instructionAssessment.hasAddressSizeVariants()) { + createTemplatesForOperandSizeAttribute(WordWidth.fromInt(addressWidth.numberOfBits / 2)); + } + } + } + + public void createTemplates(InstructionDescriptionCreator<X86InstructionDescription> instructionDescriptionCreator) { + for (X86InstructionDescription description : instructionDescriptionCreator.instructionDescriptions()) { + this.instructionDescription = description; + this.instructionAssessment = new InstructionAssessment(); + final OpcodeAssessor assessor = new OpcodeAssessor(instructionAssessment); + X86InstructionDescriptionVisitor.Static.visitInstructionDescription(assessor, description); + this.context = new X86TemplateContext(); + createTemplatesForAddressSizeAttribute(); + } + } +}