Mercurial > hg > truffle
diff graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/cisc/x86/X86Template.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/X86Template.java Sat Dec 17 19:59:18 2011 +0100 @@ -0,0 +1,447 @@ +/* + * 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.*; +import com.sun.max.asm.*; +import com.sun.max.asm.gen.*; +import com.sun.max.asm.gen.cisc.*; +import com.sun.max.asm.x86.*; +import com.sun.max.lang.*; +import com.sun.max.program.*; +import com.sun.max.util.*; + +/** + */ +public abstract class X86Template extends Template implements X86InstructionDescriptionVisitor { + private final InstructionAssessment instructionFamily; + private boolean hasSibByte; + private final X86TemplateContext context; + private HexByte instructionSelectionPrefix; + private HexByte opcode1; + private HexByte opcode2; + private ModRMGroup modRMGroup; + private ModRMGroup.Opcode modRMGroupOpcode; + private List<X86Operand> operands = new LinkedList<X86Operand>(); + private List<X86ImplicitOperand> implicitOperands = new LinkedList<X86ImplicitOperand>(); + private List<X86Parameter> parameters = new ArrayList<X86Parameter>(); + protected boolean isLabelMethodWritten; + + protected X86Template(X86InstructionDescription instructionDescription, int serial, InstructionAssessment instructionFamily, X86TemplateContext context) { + super(instructionDescription, serial); + this.instructionFamily = instructionFamily; + this.context = context; + } + + @Override + public X86InstructionDescription instructionDescription() { + return (X86InstructionDescription) super.instructionDescription(); + } + + protected X86TemplateContext context() { + return context; + } + + public HexByte instructionSelectionPrefix() { + return instructionSelectionPrefix; + } + + public HexByte opcode1() { + return opcode1; + } + + public HexByte opcode2() { + return opcode2; + } + + public boolean hasModRMByte() { + return instructionFamily.hasModRMByte(); + } + + public X86TemplateContext.ModCase modCase() { + return context.modCase(); + } + + public ModRMGroup modRMGroup() { + return modRMGroup; + } + + public ModRMGroup.Opcode modRMGroupOpcode() { + return modRMGroupOpcode; + } + + public X86TemplateContext.RMCase rmCase() { + return context.rmCase(); + } + + public boolean hasSibByte() { + return hasSibByte; + } + + protected void haveSibByte() { + hasSibByte = true; + } + + public X86TemplateContext.SibBaseCase sibBaseCase() { + return context.sibBaseCase(); + } + + public WordWidth addressSizeAttribute() { + return context.addressSizeAttribute(); + } + + public WordWidth operandSizeAttribute() { + return context.operandSizeAttribute(); + } + + private WordWidth externalCodeSizeAttribute; + + public WordWidth externalCodeSizeAttribute() { + return externalCodeSizeAttribute; + } + + protected void setExternalCodeSizeAttribute(WordWidth codeSizeAttribute) { + this.externalCodeSizeAttribute = codeSizeAttribute; + } + + @Override + public String internalName() { + String result = super.internalName(); + if (result != null && internalOperandTypeSuffix != null) { + result += internalOperandTypeSuffix; + } + return result; + } + + @Override + public String externalName() { + if (instructionDescription().externalName() != null) { + return instructionDescription().externalName(); + } + String result = super.internalName(); + if (externalOperandTypeSuffix != null) { + result += externalOperandTypeSuffix; + } + return result; + } + + private String format(HexByte parameter) { + return parameter == null ? "" : parameter.toString() + ", "; + } + + @Override + public String toString() { + return "<X86Template #" + serial() + ": " + internalName() + " " + format(instructionSelectionPrefix) + format(opcode1) + format(opcode2) + operands + ">"; + } + + private String namePrefix = ""; + + protected void useNamePrefix(String prefix) { + if (this.namePrefix.length() == 0) { + this.namePrefix = prefix; + } + } + + /** + * @see #computeRedundancyWith(X86Template) + */ + private X86Template canonicalRepresentative; + + @Override + public Template canonicalRepresentative() { + return canonicalRepresentative; + } + + private String canonicalName; + + public String canonicalName() { + if (canonicalName == null) { + canonicalName = namePrefix + internalName(); + if (implicitOperands.size() == 1) { + final X86ImplicitOperand implicitOperand = Utils.first(implicitOperands); + switch (implicitOperand.designation()) { + case DESTINATION: + case OTHER: + break; + case SOURCE: + canonicalName += "__"; + break; + } + canonicalName += "_" + implicitOperand.name(); + } else { + for (X86ImplicitOperand implicitOperand : implicitOperands) { + canonicalName += "_" + implicitOperand.name(); + } + } + } + return canonicalName; + } + + @Override + public String assemblerMethodName() { + if (isRedundant()) { + return canonicalName() + "_r" + serial(); + } + return canonicalName(); + } + + public boolean isExternalOperandOrderingInverted() { + return instructionDescription().isExternalOperandOrderingInverted(); + } + + public InstructionDescription modRMInstructionDescription() { + if (modRMGroup == null) { + return null; + } + return modRMGroup.getInstructionDescription(modRMGroupOpcode); + } + + protected <Parameter_Type extends X86Parameter> Parameter_Type addParameter(Parameter_Type parameter) { + parameters.add(parameter); + operands.add(parameter); + if (parameter instanceof X86AddressParameter) { + useNamePrefix("m_"); + } + return parameter; + } + + protected void addParameter(X86Parameter parameter, ArgumentRange argumentRange) { + addParameter(parameter); + parameter.setArgumentRange(argumentRange); + } + + protected void addParameter(X86Parameter parameter, ArgumentRange argumentRange, TestArgumentExclusion testArgumentExclusion) { + addParameter(parameter, argumentRange); + parameter.excludeTestArguments(testArgumentExclusion); + } + + protected <EnumerableArgument_Type extends Enum<EnumerableArgument_Type> & EnumerableArgument<EnumerableArgument_Type>> X86Parameter addEnumerableParameter(X86Operand.Designation designation, ParameterPlace parameterPlace, + final Enumerator<EnumerableArgument_Type> enumerator) { + return addParameter(new X86EnumerableParameter<EnumerableArgument_Type>(designation, parameterPlace, enumerator)); + } + + protected void addImplicitOperand(X86ImplicitOperand implicitOperand) { + implicitOperands.add(implicitOperand); + operands.add(implicitOperand); + } + + public List<X86ImplicitOperand> implicitOperands() { + return implicitOperands; + } + + @Override + public List<X86Operand> operands() { + return operands; + } + + @Override + public List<X86Parameter> parameters() { + return parameters; + } + + public void visitAddressingMethodCode(AddressingMethodCode addressingMethodCode, X86Operand.Designation designation) throws TemplateNotNeededException { + switch (addressingMethodCode) { + case M: { + visitOperandCode(OperandCode.Mv, designation, ArgumentRange.UNSPECIFIED, TestArgumentExclusion.NONE); + break; + } + default: { + throw ProgramError.unexpected("don't know what to do with addressing method code: " + addressingMethodCode); + } + } + } + + private String getOperandTypeSuffix(OperandTypeCode operandTypeCode) throws TemplateNotNeededException { + switch (operandTypeCode) { + case b: + return "b"; + case z: + if (operandSizeAttribute() != addressSizeAttribute()) { + throw TemplateNotNeededException.raise(); + } + case d_q: + case v: + switch (operandSizeAttribute()) { + case BITS_16: + return "w"; + case BITS_32: + return "l"; + case BITS_64: + return "q"; + default: + throw ProgramError.unexpected(); + } + default: + break; + } + return operandTypeCode.name(); + } + + private void checkSuffix(String newSuffix, String oldSuffix) { + if (oldSuffix != null) { + ProgramError.check(newSuffix.equals(oldSuffix), "conflicting operand type codes specified: " + newSuffix + " vs. " + oldSuffix); + } + } + + private String externalOperandTypeSuffix; + + private void setExternalOperandTypeSuffix(String suffix) { + checkSuffix(suffix, externalOperandTypeSuffix); + externalOperandTypeSuffix = suffix; + } + + protected void setExternalOperandTypeSuffix(OperandTypeCode operandTypeCode) throws TemplateNotNeededException { + setExternalOperandTypeSuffix(getOperandTypeSuffix(operandTypeCode)); + } + + private String internalOperandTypeSuffix; + + protected void setOperandTypeSuffix(String suffix) { + setExternalOperandTypeSuffix(suffix); + checkSuffix(suffix, internalOperandTypeSuffix); + internalOperandTypeSuffix = suffix; + } + + public void visitOperandTypeCode(OperandTypeCode operandTypeCode) throws TemplateNotNeededException { + setOperandTypeSuffix(getOperandTypeSuffix(operandTypeCode)); + } + + public void visitGeneralRegister(GeneralRegister generalRegister, X86Operand.Designation designation, ImplicitOperand.ExternalPresence externalPresence) { + addImplicitOperand(new X86ImplicitOperand(designation, externalPresence, generalRegister)); + } + + public void visitSegmentRegister(SegmentRegister segmentRegister, X86Operand.Designation designation) { + addImplicitOperand(new X86ImplicitOperand(designation, ImplicitOperand.ExternalPresence.EXPLICIT, segmentRegister)); + } + + public void visitModRMGroup(ModRMGroup modRM) throws TemplateNotNeededException { + this.modRMGroup = modRM; + final ModRMDescription instructionDescription = modRM.getInstructionDescription(context.modRMGroupOpcode()); + if (instructionDescription == null) { + TemplateNotNeededException.raise(); + } + this.modRMGroupOpcode = instructionDescription.opcode(); + setInternalName(instructionDescription.name().toLowerCase()); + } + + public void visitModCase(X86TemplateContext.ModCase modCase) throws TemplateNotNeededException { + if (context.modCase() != X86TemplateContext.ModCase.MOD_3) { + TemplateNotNeededException.raise(); + } + } + + public void visitInstructionConstraint(InstructionConstraint constraint) { + } + + protected abstract void organize_M(X86Operand.Designation designation) throws TemplateNotNeededException; + + protected <EnumerableArgument_Type extends Enum<EnumerableArgument_Type> & EnumerableArgument<EnumerableArgument_Type>> void organize_E(X86Operand.Designation designation, ParameterPlace place, + final Enumerator<EnumerableArgument_Type> registerEnumerator, TestArgumentExclusion testArgumentExclusion) throws TemplateNotNeededException { + if (context().modCase() == X86TemplateContext.ModCase.MOD_3) { + switch (context().rmCase()) { + case NORMAL: + addEnumerableParameter(designation, place, registerEnumerator).excludeTestArguments(testArgumentExclusion); + break; + default: + TemplateNotNeededException.raise(); + } + } else { + organize_M(designation); + } + } + + public void visitFloatingPointOperandCode(FloatingPointOperandCode floatingPointOperandCode, X86Operand.Designation designation, + final TestArgumentExclusion testArgumentExclusion) throws TemplateNotNeededException { + switch (floatingPointOperandCode) { + case ST_i: + addEnumerableParameter(designation, ParameterPlace.OPCODE2, FPStackRegister.ENUMERATOR).excludeTestArguments(testArgumentExclusion); + break; + default: + setOperandTypeSuffix(floatingPointOperandCode.operandTypeSuffix()); + organize_M(designation); + break; + } + } + + public void visitFPStackRegister(FPStackRegister fpStackRegister, X86Operand.Designation designation) { + addImplicitOperand(new X86ImplicitOperand(designation, ImplicitOperand.ExternalPresence.EXPLICIT, fpStackRegister)); + } + + public void visitString(String string) { + assert internalName() == null; + setInternalName(string.toLowerCase()); + } + + public void visitInteger(Integer integer, X86Operand.Designation designation) { + addImplicitOperand(new X86ImplicitOperand(designation, ImplicitOperand.ExternalPresence.EXPLICIT, new Immediate8Argument((byte) integer.intValue()))); + } + + public void visitHexByte(HexByte hexByte) throws TemplateNotNeededException { + if (opcode1 == null) { + opcode1 = hexByte; + } else if (opcode2 == null) { + opcode2 = hexByte; + } else { + if (hexByte == HexByte._66 && context.operandSizeAttribute() == WordWidth.BITS_16) { + TemplateNotNeededException.raise(); + } + assert instructionSelectionPrefix == null; + instructionSelectionPrefix = opcode1; + opcode1 = opcode2; + opcode2 = hexByte; + } + } + + /** + * Determines if this template is redundant with respect to a given template. + * Two templates are redundant if they both have the same name and operands. + * Redundant pairs of instructions are assumed to implement the same machine + * instruction semantics but have different encodings. + * + * @param other another template to compare against + * @return whether this template is redundant with respect to {@code other} + */ + public boolean computeRedundancyWith(X86Template other) { + if (canonicalRepresentative != null) { + assert canonicalRepresentative == other; + return true; + } + if (!canonicalName().equals(other.canonicalName())) { + return false; + } + if (parameters.size() != other.parameters.size()) { + return false; + } + for (int i = 0; i < parameters.size(); i++) { + if (!parameters.get(i).type().equals(other.parameters.get(i).type())) { + return false; + } + } + + canonicalRepresentative = other; + return true; + } + +}