/** * Translates the generic instruction <code>instruction</code> into an architecture-specific one. * The generated instruction(s) are added to the <code>m_ilOut</code> instruction list. * * @param instruction The instruction to translate */ private void translateInstruction(Instruction instruction) { Intrinsic intrinsic = getIntrinsicForInstruction(instruction); if (intrinsic == null) { LOGGER.debug( StringUtil.concat( "No intrinsic found for the instruction ", instruction.getInstructionName())); m_ilOut.addInstruction(instruction); return; } // get the source operands, i.e., the instruction arguments IOperand[] rgSourceOps = instruction.getOperands(); IOperand opSourceOutput = rgSourceOps[rgSourceOps.length - 1]; // get the destination operands, i.e., the arguments of the architecture-specific intrinsic Argument[] rgDestArgs = null; if (intrinsic.getArguments() != null) rgDestArgs = Arguments.parseArguments(intrinsic.getArguments()); else { LOGGER.debug( StringUtil.concat( "No arguments were defined for the intrinsic ", intrinsic.getBaseName(), ". Assuming generic arguments.")); rgDestArgs = InstructionListTranslator.createGenericArguments(rgSourceOps.length); } // check whether the number of arguments of the instruction and the intrinsic to be generated // match // the source instruction always has a result operand (the last instruction argument); in the // intrinsic // the result might be merged into one of the operands, so there might be one argument less if (rgSourceOps.length != rgDestArgs.length && rgSourceOps.length - 1 != rgDestArgs.length) { LOGGER.error( StringUtil.concat( "The arguments for the instruction ", instruction.toString(), " mapped to the intrinsic ", intrinsic.getBaseName(), " don't match")); return; } boolean bIntrinsicHasSharedResult = rgSourceOps.length - 1 == rgDestArgs.length; int nOutputArgDestIndex = InstructionListTranslator.getOutputArgumentIndex(rgDestArgs); int[] rgPermSourceToDest = new int[rgSourceOps.length]; int[] rgPermDestToSource = new int[rgDestArgs.length]; InstructionListTranslator.getArgumentPermutations( intrinsic, rgSourceOps, rgDestArgs, rgPermSourceToDest, rgPermDestToSource); if (!bIntrinsicHasSharedResult) { // the intrinsic to generate has a distinct output operand // if possible, swap commutative operands if that helps saving MOVs rgSourceOps = InstructionListTranslator.compatibilizeCommutatives( intrinsic, rgSourceOps, rgDestArgs, rgPermSourceToDest, rgPermDestToSource, nOutputArgDestIndex, bIntrinsicHasSharedResult); } else { // the intrinsic to generate has an operand which is used for shared input and output, // i.e., upon completion of the instruction, the shared operand is overwritten with the result if (opSourceOutput.equals(rgSourceOps[rgPermDestToSource[nOutputArgDestIndex]])) { // the argument of the instruction corresponding to the shared intrinsic operand // is the same as the instruction's result argument } else { if (rgSourceOps[rgSourceOps.length - 1] instanceof IOperand.IRegisterOperand) { // if possible, swap commutative operands if that helps saving MOVs rgSourceOps = InstructionListTranslator.compatibilizeCommutatives( intrinsic, rgSourceOps, rgDestArgs, rgPermSourceToDest, rgPermDestToSource, nOutputArgDestIndex, bIntrinsicHasSharedResult); } } } createInstructions( instruction, intrinsic, rgSourceOps, rgDestArgs, rgPermSourceToDest, rgPermDestToSource, nOutputArgDestIndex, bIntrinsicHasSharedResult); }
/** * Creates a copy of <code>instruction</code>. The operands are <b>not</b> deep-copied. * * @param instruction The instruction to copy */ public Instruction(Instruction instruction) { this(instruction.getInstructionName(), instruction.getIntrinsic(), instruction.getOperands()); }
/** * Finds the intrinsic for the instruction <code>instruction</code>. * * @param instruction The instruction for which to find the corresponding intrinsic. * @return The instrinsic corresponding to the instruction <code>instruction</code> */ private Intrinsic getIntrinsicForInstruction(Instruction instruction) { return m_data .getArchitectureDescription() .getIntrinsic(instruction.getInstructionName(), m_specDatatype); }